blob: c64b4bca6227e72e45086b11117fa9c78ff5932f [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
Joey Armstrong11f5a572024-01-12 19:11:32 -05002 * Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors
manikkaraj kbf256be2019-03-25 00:13:48 +05303
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Joey Armstrong3f0e2422023-07-05 18:25:41 -040017// Package core provides the utility for olt devices, flows and statistics
Scott Bakerdbd960e2020-02-28 08:57:51 -080018package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
Matteo Scandolo6056e822019-11-13 14:05:29 -080022 "encoding/hex"
Girish Gowdracefae192020-03-19 18:14:10 -070023 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "fmt"
Gamze Abaka7650be62021-02-26 10:50:36 +000025 "strconv"
serkant.uluderya4aff1862020-09-17 23:35:26 +030026 "strings"
27 "sync"
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070028 "time"
serkant.uluderya4aff1862020-09-17 23:35:26 +030029
khenaidoo106c61a2021-08-11 18:05:46 -040030 "github.com/opencord/voltha-lib-go/v7/pkg/meters"
Mahir Gunyel199570a2021-07-04 15:39:36 -070031
khenaidoo106c61a2021-08-11 18:05:46 -040032 "github.com/opencord/voltha-lib-go/v7/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070034 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040035 tp "github.com/opencord/voltha-lib-go/v7/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080036 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040037 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040038 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040039 ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
40 openoltpb2 "github.com/opencord/voltha-protos/v5/go/openolt"
41 tp_pb "github.com/opencord/voltha-protos/v5/go/tech_profile"
42 "github.com/opencord/voltha-protos/v5/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040043
Thomas Lee S94109f12020-03-03 16:39:29 +053044 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000045 "google.golang.org/grpc/codes"
46 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053047)
48
49const (
Akash Kankanala041a2122024-10-16 15:49:22 +053050 // IPProtoDhcp flow category
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070051 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Akash Kankanala041a2122024-10-16 15:49:22 +053053 // IgmpProto proto value
Girish Gowdraa09aeab2020-09-14 16:30:52 -070054 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070055
Akash Kankanala041a2122024-10-16 15:49:22 +053056 // EapEthType eapethtype value
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070057 EapEthType = 0x888e
Akash Kankanala041a2122024-10-16 15:49:22 +053058 // LldpEthType lldp ethtype value
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070059 LldpEthType = 0x88cc
Akash Kankanala041a2122024-10-16 15:49:22 +053060 // IPv4EthType IPv4 ethernet type value
Esin Karamanae41e2b2019-12-17 18:13:13 +000061 IPv4EthType = 0x800
Akash Kankanala041a2122024-10-16 15:49:22 +053062 // PPPoEDEthType PPPoE discovery ethernet type value
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030063 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070064
Akash Kankanala041a2122024-10-16 15:49:22 +053065 // ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
Andrea Campanella7acc0b92020-02-14 09:20:49 +010066 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040067
Akash Kankanala041a2122024-10-16 15:49:22 +053068 // DefaultMgmtVlan default vlan value
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070069 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053070
manikkaraj kbf256be2019-03-25 00:13:48 +053071 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070072
Akash Kankanala041a2122024-10-16 15:49:22 +053073 // Upstream constant
David K. Bainbridge82efc492019-09-04 09:57:11 -070074 Upstream = "upstream"
Akash Kankanala041a2122024-10-16 15:49:22 +053075 // Downstream constant
David K. Bainbridge82efc492019-09-04 09:57:11 -070076 Downstream = "downstream"
Akash Kankanala041a2122024-10-16 15:49:22 +053077 // Multicast constant
Esin Karamanccb714b2019-11-29 15:02:06 +000078 Multicast = "multicast"
Akash Kankanala041a2122024-10-16 15:49:22 +053079 // PacketTagType constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070080 PacketTagType = "pkt_tag_type"
Akash Kankanala041a2122024-10-16 15:49:22 +053081 // Untagged constant
David K. Bainbridge82efc492019-09-04 09:57:11 -070082 Untagged = "untagged"
Akash Kankanala041a2122024-10-16 15:49:22 +053083 // SingleTag constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070084 SingleTag = "single_tag"
Akash Kankanala041a2122024-10-16 15:49:22 +053085 // DoubleTag constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070086 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053087
88 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089
Akash Kankanala041a2122024-10-16 15:49:22 +053090 // EthType constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070091 EthType = "eth_type"
Akash Kankanala041a2122024-10-16 15:49:22 +053092 // EthDst constant
Esin Karamanccb714b2019-11-29 15:02:06 +000093 EthDst = "eth_dst"
Akash Kankanala041a2122024-10-16 15:49:22 +053094 // EthSrc constant
Girish Gowdraffa52e52022-02-16 15:48:10 -080095 EthSrc = "eth_src"
Akash Kankanala041a2122024-10-16 15:49:22 +053096 // TPID constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070097 TPID = "tpid"
Akash Kankanala041a2122024-10-16 15:49:22 +053098 // IPProto constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070099 IPProto = "ip_proto"
Akash Kankanala041a2122024-10-16 15:49:22 +0530100 // InPort constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700101 InPort = "in_port"
Akash Kankanala041a2122024-10-16 15:49:22 +0530102 // VlanVid constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700103 VlanVid = "vlan_vid"
Akash Kankanala041a2122024-10-16 15:49:22 +0530104 // VlanPcp constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700105 VlanPcp = "vlan_pcp"
106
Akash Kankanala041a2122024-10-16 15:49:22 +0530107 // UDPDst constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108 UDPDst = "udp_dst"
Akash Kankanala041a2122024-10-16 15:49:22 +0530109 // UDPSrc constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700110 UDPSrc = "udp_src"
Akash Kankanala041a2122024-10-16 15:49:22 +0530111 // Ipv4Dst constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112 Ipv4Dst = "ipv4_dst"
Akash Kankanala041a2122024-10-16 15:49:22 +0530113 // Ipv4Src constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 Ipv4Src = "ipv4_src"
Akash Kankanala041a2122024-10-16 15:49:22 +0530115 // Metadata constant
David K. Bainbridge82efc492019-09-04 09:57:11 -0700116 Metadata = "metadata"
Akash Kankanala041a2122024-10-16 15:49:22 +0530117 // TunnelID constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700118 TunnelID = "tunnel_id"
Akash Kankanala041a2122024-10-16 15:49:22 +0530119 // Output constant
David K. Bainbridge82efc492019-09-04 09:57:11 -0700120 Output = "output"
Akash Kankanala041a2122024-10-16 15:49:22 +0530121 // GroupID constant
Esin Karamanccb714b2019-11-29 15:02:06 +0000122 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700123 // Actions
124
Akash Kankanala041a2122024-10-16 15:49:22 +0530125 // PopVlan constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700126 PopVlan = "pop_vlan"
Akash Kankanala041a2122024-10-16 15:49:22 +0530127 // PushVlan constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700128 PushVlan = "push_vlan"
Akash Kankanala041a2122024-10-16 15:49:22 +0530129 // TrapToHost constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700130 TrapToHost = "trap_to_host"
Akash Kankanala041a2122024-10-16 15:49:22 +0530131 // MaxMeterBand constant
Manikkaraj kb1d51442019-07-23 10:41:02 -0400132 MaxMeterBand = 2
Akash Kankanala041a2122024-10-16 15:49:22 +0530133 // VlanPCPMask contant
Manikkaraj kb1d51442019-07-23 10:41:02 -0400134 VlanPCPMask = 0xFF
Akash Kankanala041a2122024-10-16 15:49:22 +0530135 // VlanvIDMask constant
Manikkaraj kb1d51442019-07-23 10:41:02 -0400136 VlanvIDMask = 0xFFF
Akash Kankanala041a2122024-10-16 15:49:22 +0530137 // IntfID constant
Gamze Abakafee36392019-10-03 11:17:24 +0000138 IntfID = "intfId"
Akash Kankanala041a2122024-10-16 15:49:22 +0530139 // OnuID constant
Gamze Abakafee36392019-10-03 11:17:24 +0000140 OnuID = "onuId"
Akash Kankanala041a2122024-10-16 15:49:22 +0530141 // UniID constant
Gamze Abakafee36392019-10-03 11:17:24 +0000142 UniID = "uniId"
Akash Kankanala041a2122024-10-16 15:49:22 +0530143 // PortNo constant
Gamze Abakafee36392019-10-03 11:17:24 +0000144 PortNo = "portNo"
Akash Kankanala041a2122024-10-16 15:49:22 +0530145 // AllocID constant
Gamze Abakafee36392019-10-03 11:17:24 +0000146 AllocID = "allocId"
Akash Kankanala041a2122024-10-16 15:49:22 +0530147 // GemID constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000148 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000149
Akash Kankanala041a2122024-10-16 15:49:22 +0530150 // NoneOnuID constant
Esin Karamanccb714b2019-11-29 15:02:06 +0000151 NoneOnuID = -1
Akash Kankanala041a2122024-10-16 15:49:22 +0530152 // NoneUniID constant
Esin Karamanccb714b2019-11-29 15:02:06 +0000153 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700154
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700155 // Max number of flows that can be queued per ONU
156 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530157
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700158 bitMapPrefix = "0b"
159 pbit1 = '1'
160)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400161
Gamze Abakafee36392019-10-03 11:17:24 +0000162type schedQueue struct {
Akash Kankanala041a2122024-10-16 15:49:22 +0530163 tpInst interface{}
164 flowMetadata *ofp.FlowMetadata
Gamze Abakafee36392019-10-03 11:17:24 +0000165 direction tp_pb.Direction
166 intfID uint32
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530167 nniIntfID uint32
Gamze Abakafee36392019-10-03 11:17:24 +0000168 onuID uint32
169 uniID uint32
170 tpID uint32
171 uniPort uint32
Gamze Abakafee36392019-10-03 11:17:24 +0000172 meterID uint32
Gamze Abakafee36392019-10-03 11:17:24 +0000173}
174
Gamze Abaka7650be62021-02-26 10:50:36 +0000175type flowContext struct {
Akash Kankanala041a2122024-10-16 15:49:22 +0530176 classifier map[string]interface{}
177 action map[string]interface{}
178 logicalFlow *ofp.OfpFlowStats
179 pbitToGem map[uint32]uint32
180 gemToAes map[uint32]bool
Gamze Abaka7650be62021-02-26 10:50:36 +0000181 intfID uint32
182 onuID uint32
183 uniID uint32
184 portNo uint32
Gamze Abaka7650be62021-02-26 10:50:36 +0000185 allocID uint32
186 gemPortID uint32
187 tpID uint32
Gamze Abaka7650be62021-02-26 10:50:36 +0000188}
189
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700190// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
191// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
192// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
193// flow and processes it serially
194type flowControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400195 ctx context.Context // Flow handler context
khenaidoodc2116e2021-10-19 17:33:19 -0400196 flow *ofp.OfpFlowStats // Flow message
197 flowMetadata *ofp.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
198 errChan *chan error // channel to report the Flow handling error
Akash Kankanala041a2122024-10-16 15:49:22 +0530199 addFlow bool // if true flow to be added, else removed
Esin Karamanccb714b2019-11-29 15:02:06 +0000200}
201
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400202// OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530203type OpenOltFlowMgr struct {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700204 techprofile tp.TechProfileIf
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700205 deviceHandler *DeviceHandler
206 grpMgr *OpenOltGroupMgr
207 resourceMgr *rsrcMgr.OpenOltResourceMgr
208
Akash Kankanala041a2122024-10-16 15:49:22 +0530209 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 // packet in gem port local cache
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700210
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700211 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
212 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700213 incomingFlows []chan flowControlBlock
214 stopFlowHandlerRoutine []chan bool
215 flowHandlerRoutineActive []bool
Akash Kankanala041a2122024-10-16 15:49:22 +0530216 packetInGemPortLock sync.RWMutex
217
218 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
manikkaraj kbf256be2019-03-25 00:13:48 +0530219}
220
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000221// CloseKVClient closes open KV clients
222func (f *OpenOltFlowMgr) CloseKVClient(ctx context.Context) {
223 if f.techprofile != nil {
224 f.techprofile.CloseKVClient(ctx)
225 }
226}
227
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400228// NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700229func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000230 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530231 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530232 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530233
manikkaraj kbf256be2019-03-25 00:13:48 +0530234 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700235 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700236 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530237 flowMgr.resourceMgr = rMgr
yasin saplid0566272021-12-21 09:10:30 +0000238 // dh.totalPonPorts is reserved for NNI trap flows. It doesn't need a tech profile
239 if ponPortIdx != dh.totalPonPorts {
240 if err = flowMgr.populateTechProfileForCurrentPonPort(ctx); err != nil {
241 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
242 return nil
243 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530244 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530245 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700246
247 // Create a slice of buffered channels for handling concurrent flows per ONU.
248 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700249 flowMgr.incomingFlows = make([]chan flowControlBlock, plt.MaxOnusPerPon+1)
250 flowMgr.stopFlowHandlerRoutine = make([]chan bool, plt.MaxOnusPerPon+1)
251 flowMgr.flowHandlerRoutineActive = make([]bool, plt.MaxOnusPerPon+1)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700252 for i := range flowMgr.incomingFlows {
253 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
Girish Gowdraae56c722021-11-22 14:31:11 -0800254 flowMgr.stopFlowHandlerRoutine[i] = make(chan bool)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700255 // Spin up a go routine to handling incoming flows (add/remove).
256 // There will be on go routine per ONU.
257 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700258 flowMgr.flowHandlerRoutineActive[i] = true
259 go flowMgr.perOnuFlowHandlerRoutine(i, flowMgr.incomingFlows[i], flowMgr.stopFlowHandlerRoutine[i])
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700260 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700261
Akash Kankanala041a2122024-10-16 15:49:22 +0530262 // load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700263 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000264 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530265 return &flowMgr
266}
267
Kent Hagermane6ff1012020-07-14 15:07:53 -0400268func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
yasin saplid0566272021-12-21 09:10:30 +0000269 // In case of nni trap flow
270 if deviceFlow.AccessIntfId == -1 {
yasin saplibddc2d72022-02-08 13:10:17 +0000271 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), flowFromCore)
yasin saplid0566272021-12-21 09:10:30 +0000272 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700273 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
274 // Flow is not replicated in this case, we need to register the flow for a single gem-port
yasin saplibddc2d72022-02-08 13:10:17 +0000275 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700276 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
277 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
278 for _, gemPort := range deviceFlow.PbitToGemport {
yasin saplibddc2d72022-02-08 13:10:17 +0000279 if err := f.resourceMgr.RegisterFlowIDForGem(ctx, gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700280 return err
281 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700282 }
Gamze Abakafee36392019-10-03 11:17:24 +0000283 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700284 return nil
285}
286
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530287func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, nni_port uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000288 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
khenaidoodc2116e2021-10-19 17:33:19 -0400289 UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000290 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530291 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700292 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530293
Neha Sharma96b7bf22020-06-15 10:37:32 +0000294 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530295 "device-id": f.deviceHandler.device.Id,
296 "intf-id": intfID,
297 "onu-id": onuID,
298 "uni-id": uniID,
299 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700300 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530301 "action": actionInfo,
302 "usmeter-iD": UsMeterID,
303 "dsmeter-iD": DsMeterID,
304 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400305 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
306 // is because the flow is an NNI flow and there would be no onu resources associated with it
307 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400308 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200309 cause := "no-onu-id-for-flow"
310 fields := log.Fields{
311 "onu": onuID,
312 "port-no": portNo,
313 "classifer": classifierInfo,
314 "action": actionInfo,
315 "device-id": f.deviceHandler.device.Id}
316 logger.Errorw(ctx, cause, fields)
317 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530318 }
319
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700320 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000321 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530322 "uni": uni,
323 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530324
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700325 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
326 "device-id": f.deviceHandler.device.Id,
327 "intf-id": intfID,
328 "onu-id": onuID,
329 "uni-id": uniID,
330 "port-no": portNo,
331 "classifier": classifierInfo,
332 "action": actionInfo,
333 "usmeter-id": UsMeterID,
334 "dsmeter-id": DsMeterID,
335 "tp-id": TpID})
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530336 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, nni_port, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700337 if allocID == 0 || gemPorts == nil || TpInst == nil {
338 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
339 return olterrors.NewErrNotFound(
340 "alloc-id-gem-ports-tp-unavailable",
341 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400342 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700343 args := make(map[string]uint32)
344 args[IntfID] = intfID
345 args[OnuID] = onuID
346 args[UniID] = uniID
347 args[PortNo] = portNo
348 args[AllocID] = allocID
349
350 /* Flows can be added specific to gemport if p-bits are received.
351 * If no pbit mentioned then adding flows for all gemports
352 */
Gamze Abaka6d0a64f2021-11-18 08:08:33 +0000353 return f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530354}
355
salmansiddiqui7ac62132019-08-22 03:58:50 +0000356// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Girish Gowdraf3728b12022-02-02 21:46:51 -0800357// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530358func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
nikesh.krishnan81ec7442023-10-31 17:19:34 +0530359 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530360 log.Fields{"dir": sq.direction,
361 "intf-id": sq.intfID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530362 "nniIntfID": sq.nniIntfID,
Shrey Baid26912972020-04-16 21:02:31 +0530363 "onu-id": sq.onuID,
364 "uni-id": sq.uniID,
365 "tp-id": sq.tpID,
366 "meter-id": sq.meterID,
367 "tp-inst": sq.tpInst,
368 "flowmetadata": sq.flowMetadata,
369 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400370
Girish Gowdra6071f382021-12-14 12:52:04 +0530371 direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000372 if err != nil {
373 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400374 }
375
Girish Gowdraf3728b12022-02-02 21:46:51 -0800376 var TrafficShaping *tp_pb.TrafficShapingInfo
377 if sq.flowMetadata == nil || len(sq.flowMetadata.Meters) != 1 {
378 return olterrors.NewErrInvalidValue(log.Fields{
379 "reason": "invalid-meter-config",
380 "meter-id": sq.meterID,
381 "device-id": f.deviceHandler.device.Id}, nil)
382 }
383
384 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
385 return olterrors.NewErrInvalidValue(log.Fields{
386 "reason": "invalid-meter-config",
387 "meter-id": sq.meterID,
388 "device-id": f.deviceHandler.device.Id}, nil)
389 }
390
391 var SchedCfg *tp_pb.SchedulerConfig
mgouda86543582025-10-29 20:58:16 +0530392 switch sq.direction {
393 case tp_pb.Direction_UPSTREAM:
Girish Gowdraf3728b12022-02-02 21:46:51 -0800394 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
mgouda86543582025-10-29 20:58:16 +0530395 case tp_pb.Direction_DOWNSTREAM:
Girish Gowdraf3728b12022-02-02 21:46:51 -0800396 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
397 }
398 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
399 TrafficSched[0].TechProfileId = sq.tpID
400
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401 /* Lets make a simple assumption that if the meter-id is present on the KV store,
402 * then the scheduler and queues configuration is applied on the OLT device
403 * in the given direction.
404 */
yasin saplibddc2d72022-02-08 13:10:17 +0000405 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400406 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530407 return olterrors.NewErrNotFound("meter",
408 log.Fields{"intf-id": sq.intfID,
409 "onu-id": sq.onuID,
410 "uni-id": sq.uniID,
411 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400412 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000413
Girish Gowdraf3728b12022-02-02 21:46:51 -0800414 // update reference count and return if the meter was already installed before
Girish Gowdra6071f382021-12-14 12:52:04 +0530415 if meterInfo != nil && meterInfo.MeterID == sq.meterID {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800416 logger.Infow(ctx, "scheduler-already-created-for-direction",
Girish Gowdra6071f382021-12-14 12:52:04 +0530417 log.Fields{"device-id": f.deviceHandler.device.Id, "direction": direction, "meter-id": sq.meterID})
yasin saplibddc2d72022-02-08 13:10:17 +0000418 if err = f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, direction, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800419 return err
420 }
421
422 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); allocExists {
423 // Alloc object was already created as part of flow setup on another uni of the onu for the same service.
424 // Just create gem ports and traffic queues on the current uni for the given service
425 logger.Infow(ctx, "alloc in use on another uni, schedulers already created, creating queues only",
426 log.Fields{"intf-id": sq.intfID,
427 "onu-id": sq.onuID,
428 "uni-id": sq.uniID,
429 "tp-id": sq.tpID,
430 "device-id": f.deviceHandler.device.Id})
431 // The upstream scheduler is already created. We only need to create the queues
432 // If there are multiple upstream flows on a given uni, then it is possible that
433 // we call pushTrafficQueues multiple times, but that is OK as BAL returns OK.
434 // TODO: Find better mechanism to not duplicate request.
435 if err = f.pushTrafficQueues(ctx, sq, TrafficSched); err != nil {
436 return olterrors.NewErrAdapter("failure-pushing-traffic-queues-to-device",
437 log.Fields{"intf-id": sq.intfID,
438 "direction": sq.direction,
439 "device-id": f.deviceHandler.device.Id}, err)
440 }
441 } else {
442 logger.Infow(ctx, "alloc not in use on another uni, only meter ref cnt updated",
443 log.Fields{"intf-id": sq.intfID,
444 "onu-id": sq.onuID,
445 "uni-id": sq.uniID,
446 "tp-id": sq.tpID,
447 "device-id": f.deviceHandler.device.Id})
448 }
449 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400450 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000451
Neha Sharma96b7bf22020-06-15 10:37:32 +0000452 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530453 log.Fields{
454 "meter-id": sq.meterID,
Girish Gowdra6071f382021-12-14 12:52:04 +0530455 "direction": direction,
Shrey Baid26912972020-04-16 21:02:31 +0530456 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000457
Girish Gowdraa482f272021-03-24 23:04:19 -0700458 found := false
459 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000460 if sq.flowMetadata != nil {
461 for _, meter := range sq.flowMetadata.Meters {
462 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700463 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700464 meterInfo.RefCnt = 1 // initialize it to 1, since this is the first flow that referenced the meter id.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000465 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700466 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530467 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700468 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400469 break
470 }
471 }
472 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000473 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400474 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700475 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530476 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800477 "reason": "Could-not-get-meterbands-from-flowMetadata",
478 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530479 "meter-id": sq.meterID,
480 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400481 }
Gamze Abaka01174422021-03-10 06:55:27 +0000482
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700483 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530484 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
485 log.Fields{"intf-id": sq.intfID,
486 "direction": sq.direction,
487 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400488 }
489
salmansiddiqui7ac62132019-08-22 03:58:50 +0000490 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400491 * store the meter id on the KV store, for further reference.
492 */
yasin saplibddc2d72022-02-08 13:10:17 +0000493 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530494 return olterrors.NewErrAdapter("failed-updating-meter-id",
495 log.Fields{"onu-id": sq.onuID,
496 "meter-id": sq.meterID,
497 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400498 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000499 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Girish Gowdra6071f382021-12-14 12:52:04 +0530500 log.Fields{"direction": direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700501 "meter-info": meterInfo,
502 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503 return nil
504}
505
Girish Gowdraf3728b12022-02-02 21:46:51 -0800506func (f *OpenOltFlowMgr) pushTrafficQueues(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
507 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
508 if err != nil {
509 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
510 log.Fields{"intf-id": sq.intfID,
511 "direction": sq.direction,
512 "device-id": f.deviceHandler.device.Id}, err)
513 }
514 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
515 log.Fields{"direction": sq.direction,
516 "traffic-queues": trafficQueues,
517 "device-id": f.deviceHandler.device.Id})
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530518 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, NetworkIntfId: sq.nniIntfID, OnuId: sq.onuID,
Girish Gowdraf3728b12022-02-02 21:46:51 -0800519 UniId: sq.uniID, PortNo: sq.uniPort,
520 TrafficQueues: trafficQueues,
521 TechProfileId: TrafficSched[0].TechProfileId}
Akash Kankanala041a2122024-10-16 15:49:22 +0530522 if _, err = f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800523 if len(queues.TrafficQueues) > 1 {
524 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
525 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
526 }
527 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
528 }
529 return err
530}
531
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700532func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700533 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000534
535 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530536 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
537 log.Fields{"intf-id": sq.intfID,
538 "direction": sq.direction,
539 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000540 }
541
Gamze Abakacb0e6772021-06-10 08:32:12 +0000542 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
543 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
544 log.Fields{
545 "direction": sq.direction,
546 "TrafficScheds": TrafficSched,
547 "device-id": f.deviceHandler.device.Id,
548 "intfID": sq.intfID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530549 "nniIntfID": sq.nniIntfID,
Gamze Abakacb0e6772021-06-10 08:32:12 +0000550 "onuID": sq.onuID,
551 "uniID": sq.uniID})
552 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
553 IntfId: sq.intfID, OnuId: sq.onuID,
554 UniId: sq.uniID, PortNo: sq.uniPort,
555 TrafficScheds: TrafficSched}); err != nil {
556 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
557 }
558 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
559 "direction": sq.direction,
560 "traffic-queues": trafficQueues,
561 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000562 }
563
564 // On receiving the CreateTrafficQueues request, the driver should create corresponding
565 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000566 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530567 log.Fields{"direction": sq.direction,
568 "traffic-queues": trafficQueues,
569 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000570 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530571 NetworkIntfId: sq.nniIntfID,
572 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000573 TrafficQueues: trafficQueues,
574 TechProfileId: TrafficSched[0].TechProfileId}
575 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
576 if len(queues.TrafficQueues) > 1 {
577 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
578 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
579 }
580 f.revertScheduler(ctx, sq, TrafficSched)
Shrey Baid26912972020-04-16 21:02:31 +0530581 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000582 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000583 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530584 "direction": sq.direction,
585 "traffic-queues": trafficQueues,
586 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000587
Esin Karamanccb714b2019-11-29 15:02:06 +0000588 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700589 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000590 if len(multicastTrafficQueues) > 0 {
Akash Kankanala041a2122024-10-16 15:49:22 +0530591 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present { // assumed that there is only one queue per PON for the multicast service
592 // the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
593 // just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000594 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000595 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700596 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000597 gemPortID: multicastQueuePerPonPort.GemportId,
598 servicePriority: multicastQueuePerPonPort.Priority,
599 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700600 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Akash Kankanala041a2122024-10-16 15:49:22 +0530601 // also store the queue info in kv store
yasin saplibddc2d72022-02-08 13:10:17 +0000602 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700603 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400604 return err
605 }
Shrey Baid26912972020-04-16 21:02:31 +0530606
Neha Sharma96b7bf22020-06-15 10:37:32 +0000607 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000608 }
609 }
610 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000611 return nil
612}
613
Girish Gowdraf3728b12022-02-02 21:46:51 -0800614// RemoveQueues removes the traffic queues from the device based on the given schedQueue info
615func (f *OpenOltFlowMgr) RemoveQueues(ctx context.Context, sq schedQueue) error {
616 var err error
617 logger.Infow(ctx, "removing-queue-in-olt",
618 log.Fields{
619 "direction": sq.direction,
620 "intf-id": sq.intfID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530621 "nniIntfID": sq.nniIntfID,
Girish Gowdraf3728b12022-02-02 21:46:51 -0800622 "onu-id": sq.onuID,
623 "uni-id": sq.uniID,
624 "uni-port": sq.uniPort,
625 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400626
Girish Gowdraf3728b12022-02-02 21:46:51 -0800627 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
628 if err != nil {
629 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
630 log.Fields{
631 "intf-id": sq.intfID,
632 "direction": sq.direction,
633 "device-id": f.deviceHandler.device.Id}, err)
634 }
635
636 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
637 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530638 NetworkIntfId: sq.nniIntfID,
639 UniId: sq.uniID, PortNo: sq.uniPort,
Girish Gowdraf3728b12022-02-02 21:46:51 -0800640 TrafficQueues: TrafficQueues,
641 TechProfileId: sq.tpID}); err != nil {
642 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
643 log.Fields{
644 "intf-id": sq.intfID,
645 "traffic-queues": TrafficQueues,
646 "device-id": f.deviceHandler.device.Id}, err)
647 }
648 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
649
650 return err
651}
652
653// RemoveScheduler removes the traffic scheduler from the device based on the given schedQueue info
654func (f *OpenOltFlowMgr) RemoveScheduler(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400655 var Direction string
656 var SchedCfg *tp_pb.SchedulerConfig
657 var err error
Girish Gowdraf3728b12022-02-02 21:46:51 -0800658 logger.Infow(ctx, "removing-scheduler-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530659 log.Fields{
660 "direction": sq.direction,
661 "intf-id": sq.intfID,
662 "onu-id": sq.onuID,
663 "uni-id": sq.uniID,
664 "uni-port": sq.uniPort,
665 "device-id": f.deviceHandler.device.Id})
mgouda86543582025-10-29 20:58:16 +0530666 switch sq.direction {
667 case tp_pb.Direction_UPSTREAM:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700668 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400669 Direction = "upstream"
mgouda86543582025-10-29 20:58:16 +0530670 case tp_pb.Direction_DOWNSTREAM:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700671 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400672 Direction = "downstream"
673 }
674
Girish Gowdraa482f272021-03-24 23:04:19 -0700675 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 -0400676
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700677 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000678 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000679
Girish Gowdraf3728b12022-02-02 21:46:51 -0800680 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
681 IntfId: sq.intfID, OnuId: sq.onuID,
682 UniId: sq.uniID, PortNo: sq.uniPort,
683 TrafficScheds: TrafficSched}); err != nil {
684 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530685 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800686 "intf-id": sq.intfID,
687 "traffic-schedulers": TrafficSched,
688 "onu-id": sq.onuID,
689 "uni-id": sq.uniID,
690 "uni-port": sq.uniPort}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000691 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400692
Girish Gowdraf3728b12022-02-02 21:46:51 -0800693 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
694 log.Fields{"device-id": f.deviceHandler.device.Id,
695 "intf-id": sq.intfID,
696 "onu-id": sq.onuID,
697 "uni-id": sq.uniID,
698 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400699
Girish Gowdraf3728b12022-02-02 21:46:51 -0800700 if sq.direction == tp_pb.Direction_UPSTREAM {
701 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
702 // Delete the TCONT on the ONU.
703 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
yasin saplibddc2d72022-02-08 13:10:17 +0000704 tpPath := f.getTPpath(ctx, uni, sq.tpID)
Akash Kankanala041a2122024-10-16 15:49:22 +0530705 if err = f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800706 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Gamze Abakacb0e6772021-06-10 08:32:12 +0000707 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800708 "intf": sq.intfID,
709 "onu-id": sq.onuID,
710 "uni-id": sq.uniID,
711 "device-id": f.deviceHandler.device.Id,
712 "alloc-id": allocID})
Gamze Abakacb0e6772021-06-10 08:32:12 +0000713 }
714 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000715
716 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400717 * delete the meter id on the KV store.
718 */
Girish Gowdraf3728b12022-02-02 21:46:51 -0800719 err = f.removeMeterReference(ctx, Direction, sq)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400720 return err
721}
722
Girish Gowdra197acc12021-08-16 10:59:45 -0700723// We are trying to force remove the schedulers and queues here if one exists for the given key.
724// We ignore any errors encountered in the process. The errors most likely are encountered when
725// the schedulers and queues are already cleared for the given key.
726func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
Girish Gowdra197acc12021-08-16 10:59:45 -0700727 var schedCfg *tp_pb.SchedulerConfig
Girish Gowdra197acc12021-08-16 10:59:45 -0700728 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
729 log.Fields{
730 "direction": sq.direction,
731 "intf-id": sq.intfID,
732 "onu-id": sq.onuID,
733 "uni-id": sq.uniID,
734 "uni-port": sq.uniPort,
735 "tp-id": sq.tpID,
736 "device-id": f.deviceHandler.device.Id})
mgouda86543582025-10-29 20:58:16 +0530737 switch sq.direction {
738 case tp_pb.Direction_UPSTREAM:
Girish Gowdra197acc12021-08-16 10:59:45 -0700739 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
mgouda86543582025-10-29 20:58:16 +0530740 case tp_pb.Direction_DOWNSTREAM:
Girish Gowdra197acc12021-08-16 10:59:45 -0700741 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
742 }
743
744 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
745 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
746 TrafficSched[0].TechProfileId = sq.tpID
747
748 // Remove traffic queues. Ignore any errors, just log them.
749 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
750 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
751 "direction": sq.direction,
752 "intf-id": sq.intfID,
753 "onu-id": sq.onuID,
754 "uni-id": sq.uniID,
755 "uni-port": sq.uniPort,
756 "tp-id": sq.tpID,
757 "device-id": f.deviceHandler.device.Id,
758 "err": err})
759 } else {
760 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
761 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
762 UniId: sq.uniID, PortNo: sq.uniPort,
763 TrafficQueues: TrafficQueues,
764 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
765 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
766 "direction": sq.direction,
767 "intf-id": sq.intfID,
768 "onu-id": sq.onuID,
769 "uni-id": sq.uniID,
770 "uni-port": sq.uniPort,
771 "tp-id": sq.tpID,
772 "device-id": f.deviceHandler.device.Id,
773 "err": err})
Girish Gowdra197acc12021-08-16 10:59:45 -0700774 } else {
775 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
776 "direction": sq.direction,
777 "intf-id": sq.intfID,
778 "onu-id": sq.onuID,
779 "uni-id": sq.uniID,
780 "uni-port": sq.uniPort,
781 "tp-id": sq.tpID})
782 }
783 }
784
785 // Remove traffic schedulers. Ignore any errors, just log them.
Akash Kankanala041a2122024-10-16 15:49:22 +0530786 if _, err := f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Gowdra197acc12021-08-16 10:59:45 -0700787 IntfId: sq.intfID, OnuId: sq.onuID,
788 UniId: sq.uniID, PortNo: sq.uniPort,
789 TrafficScheds: TrafficSched}); err != nil {
790 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
791 "direction": sq.direction,
792 "intf-id": sq.intfID,
793 "onu-id": sq.onuID,
794 "uni-id": sq.uniID,
795 "uni-port": sq.uniPort,
796 "tp-id": sq.tpID,
797 "device-id": f.deviceHandler.device.Id,
798 "err": err})
799 } else {
800 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
801 "direction": sq.direction,
802 "intf-id": sq.intfID,
803 "onu-id": sq.onuID,
804 "uni-id": sq.uniID,
805 "uni-port": sq.uniPort,
806 "tp-id": sq.tpID})
807 }
808}
809
Gamze Abakafee36392019-10-03 11:17:24 +0000810// This function allocates tconts and GEM ports for an ONU
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530811func (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 +0000812 var allocIDs []uint32
813 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530814 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530815 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000816 var err error
yasin saplibddc2d72022-02-08 13:10:17 +0000817 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, onuID, uniID)
818 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, onuID, uniID)
819 tpPath := f.getTPpath(ctx, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530820
Neha Sharma96b7bf22020-06-15 10:37:32 +0000821 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530822 "intf-id": intfID,
823 "onu-id": onuID,
824 "uni-id": uniID,
825 "device-id": f.deviceHandler.device.Id,
826 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530827
Manikkaraj kb1d51442019-07-23 10:41:02 -0400828 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700829 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000830 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000831 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530832 log.Fields{
833 "path": tpPath,
834 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700835 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000836 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530837 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000838 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530839 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700840 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530841 "tp-id": TpID,
842 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000843 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530844 }
yasin saplibddc2d72022-02-08 13:10:17 +0000845 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700846 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400847 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530848 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000849 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530850 log.Fields{
851 "uni": uni,
852 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530853 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530854 }
Gamze Abakafee36392019-10-03 11:17:24 +0000855
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700856 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700857 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700858 if UsMeterID != 0 {
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530859 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, nniIntfID: nniIntfID, onuID: onuID, uniID: uniID, tpID: TpID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700860 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
861 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000862 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700863 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700864 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700865 "onu-id": onuID,
866 "uni-id": uniID,
867 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700868 "meter-id": UsMeterID,
869 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000870 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700871 return 0, nil, nil
872 }
873 }
874 if DsMeterID != 0 {
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530875 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, nniIntfID: nniIntfID, onuID: onuID, uniID: uniID, tpID: TpID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700876 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
877 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000878 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700879 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700880 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700881 "onu-id": onuID,
882 "uni-id": uniID,
883 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700884 "meter-id": DsMeterID,
885 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000886 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700887 return 0, nil, nil
888 }
889 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700890 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700891 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700892 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700893 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700894 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000895
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700896 if tpInstanceExists {
897 return allocID, gemPortIDs, techProfileInstance
898 }
899
900 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700901 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700902 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000903 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700904 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700905 "intf-id": intfID,
906 "onu-id": onuID,
907 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700908 "alloc-ids": allocIDs,
909 "gemports": allgemPortIDs,
910 "device-id": f.deviceHandler.device.Id})
911 // Send Tconts and GEM ports to KV store
912 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530913 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400914 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700915 // CreateSchedulerQueues for EPON needs to be implemented here
916 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700917 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700918 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700919 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700920 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700921 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700922
923 if tpInstanceExists {
924 return allocID, gemPortIDs, techProfileInstance
925 }
926
927 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700928 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700929 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000930 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700931 log.Fields{
932 "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)
937 return allocID, gemPortIDs, techProfileInstance
938 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000939 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700940 log.Fields{
941 "tpInst": tpInst})
942 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530943 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530944}
945
npujarec5762e2020-01-01 14:08:48 +0530946func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000947 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530948 log.Fields{
949 "intf-id": intfID,
950 "onu-id": onuID,
951 "uni-id": uniID,
952 "alloc-id": allocID,
953 "gemport-ids": gemPortIDs,
954 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530955 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
yasin saplibddc2d72022-02-08 13:10:17 +0000956 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, onuID, uniID, allocID); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000957 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 +0530958 }
yasin saplibddc2d72022-02-08 13:10:17 +0000959 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, onuID, uniID, gemPortIDs); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000960 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 +0530961 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700962
Neha Sharma96b7bf22020-06-15 10:37:32 +0000963 logger.Infow(ctx, "stored-tconts-and-gem-into-kv-store-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400964 for _, gemPort := range gemPortIDs {
yasin saplibddc2d72022-02-08 13:10:17 +0000965 if err := f.resourceMgr.AddGemToOnuGemInfo(ctx, onuID, gemPort); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000966 logger.Errorw(ctx, "error-while-uploading-onugeminfos-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "gemPort": gemPort})
967 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400968 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530969}
970
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700971func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530972 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000973 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700974 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
975 var err error
pnalmas937a24d2025-01-16 18:48:30 +0530976 f.techprofile, err = tp.NewTechProfile(ctx, intfID, f.resourceMgr.DeviceID, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700977 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
978 if err != nil || f.techprofile == nil {
979 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
980 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
981 }
982 logger.Debugw(ctx, "init-tech-profile-done",
983 log.Fields{
984 "intf-id": intfID,
985 "device-id": f.deviceHandler.device.Id})
986 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700987 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530988 }
989 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700990 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
991 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 +0530992}
993
Gamze Abaka7650be62021-02-26 10:50:36 +0000994func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Girish Gowdraffa52e52022-02-16 15:48:10 -0800995 flowContext.classifier[PacketTagType] = SingleTag
996 // extract the cvid/inner-vid from the write metadata
997 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
998 if writeMetadata != 0 {
999 // Writemetadata field is 8 bytes
1000 // cvid is on the outer most two bytes of the write metadata
1001 cvid := (writeMetadata & 0xffff000000000000) >> 48
1002 // if the cvid does not match the classifier vlan, then this indicates it is a double tagged packet
1003 if cvid != flowContext.classifier[VlanVid] && cvid != 0 {
1004 flowContext.classifier[PacketTagType] = DoubleTag
1005 }
1006 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001007 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301008 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001009 "uplinkClassifier": flowContext.classifier,
1010 "uplinkAction": flowContext.action})
1011 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301012}
1013
Gamze Abaka7650be62021-02-26 10:50:36 +00001014func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
1015 downlinkClassifier := flowContext.classifier
1016 downlinkAction := flowContext.action
Girish Gowdraffa52e52022-02-16 15:48:10 -08001017 // default to single tag. If we detect an inner cvid from write-metadata, then we mark the PacketTagType as DoubleTag
1018 downlinkClassifier[PacketTagType] = SingleTag
1019 // extract the cvid/inner-vid from the write metadata
1020 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
1021 if writeMetadata != 0 {
1022 // Writemetadata field is 8 bytes
1023 // cvid is on the outer most two bytes of the write metadata
1024 if cvid := (writeMetadata & 0xffff000000000000) >> 48; cvid != 0 {
1025 downlinkClassifier[PacketTagType] = DoubleTag
1026 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301027 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001028 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301029 log.Fields{
1030 "downlinkClassifier": downlinkClassifier,
1031 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001032
Girish Gowdraffa52e52022-02-16 15:48:10 -08001033 // If Pop Vlan action is specified, set the vlan to be popped from the classifier vlan match field.
1034 // The matched vlan is the one that is getting popped.
1035 if val, ok := downlinkAction[PopVlan]; ok && val.(bool) {
1036 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1037 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
1038 if ok {
1039 downlinkAction[VlanVid] = dlClVid & 0xfff
1040 }
Girish Gowdra26f344b2019-10-23 14:39:13 +05301041 }
1042
Gamze Abaka7650be62021-02-26 10:50:36 +00001043 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301044}
1045
Gamze Abaka7650be62021-02-26 10:50:36 +00001046func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001047 intfID := flowContext.intfID
1048 onuID := flowContext.onuID
1049 uniID := flowContext.uniID
1050 classifier := flowContext.classifier
1051 action := flowContext.action
1052 allocID := flowContext.allocID
1053 gemPortID := flowContext.gemPortID
1054 tpID := flowContext.tpID
1055 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001056 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301057 log.Fields{
1058 "intf-id": intfID,
1059 "onu-id": onuID,
1060 "uni-id": uniID,
1061 "device-id": f.deviceHandler.device.Id,
1062 "classifier": classifier,
1063 "action": action,
1064 "direction": direction,
1065 "alloc-id": allocID,
1066 "gemport-id": gemPortID,
1067 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001068
yasin saplibddc2d72022-02-08 13:10:17 +00001069 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001070 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001071 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301072 log.Fields{
1073 "device-id": f.deviceHandler.device.Id,
1074 "intf-id": intfID,
1075 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001076 return nil
yasin saplid0566272021-12-21 09:10:30 +00001077 } else if err != nil {
1078 logger.Errorw(ctx, "aborting-addSymmetricDataPathFlow--flow-may-already-exist",
1079 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1080 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301081 }
yasin saplid0566272021-12-21 09:10:30 +00001082
David K. Bainbridge794735f2020-02-11 21:01:37 -08001083 classifierProto, err := makeOpenOltClassifierField(classifier)
1084 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301085 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301086 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001087 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301088 log.Fields{
1089 "classifier": *classifierProto,
1090 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001091 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001092 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301093 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301094 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001095 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301096 log.Fields{
1097 "action": *actionProto,
1098 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001099 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301100 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301101 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001102 log.Fields{
1103 "classifier": classifier,
1104 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301105 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001106 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301107 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001108
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001109 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001110 OnuId: int32(onuID),
1111 UniId: int32(uniID),
1112 FlowId: logicalFlow.Id,
1113 FlowType: direction,
1114 AllocId: int32(allocID),
1115 NetworkIntfId: int32(networkIntfID),
1116 GemportId: int32(gemPortID),
1117 Classifier: classifierProto,
1118 Action: actionProto,
1119 Priority: int32(logicalFlow.Priority),
1120 Cookie: logicalFlow.Cookie,
1121 PortNo: flowContext.portNo,
1122 TechProfileId: tpID,
1123 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1124 PbitToGemport: flowContext.pbitToGem,
1125 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001126 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001127 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001128 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301129 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001130 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301131 log.Fields{"direction": direction,
1132 "device-id": f.deviceHandler.device.Id,
1133 "flow": flow,
1134 "intf-id": intfID,
1135 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001136
David K. Bainbridge794735f2020-02-11 21:01:37 -08001137 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301138}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001139
Gamze Abaka7650be62021-02-26 10:50:36 +00001140func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001141 intfID := flowContext.intfID
1142 onuID := flowContext.onuID
1143 uniID := flowContext.uniID
1144 logicalFlow := flowContext.logicalFlow
1145 classifier := flowContext.classifier
1146 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301147
Neha Sharma96b7bf22020-06-15 10:37:32 +00001148 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301149 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301150 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001151 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301152 "action": action,
1153 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001154 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301155 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301156
1157 // Clear the action map
1158 for k := range action {
1159 delete(action, k)
1160 }
1161
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001162 action[TrapToHost] = true
1163 classifier[UDPSrc] = uint32(68)
1164 classifier[UDPDst] = uint32(67)
1165 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301166
yasin saplibddc2d72022-02-08 13:10:17 +00001167 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001168 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001169 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301170 log.Fields{
1171 "device-id": f.deviceHandler.device.Id,
1172 "intf-id": intfID,
1173 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001174 return nil
yasin saplid0566272021-12-21 09:10:30 +00001175 } else if err != nil {
1176 logger.Errorw(ctx, "aborting-addDHCPTrapFlow--flow-may-already-exist",
1177 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1178 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301179 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301180
Neha Sharma96b7bf22020-06-15 10:37:32 +00001181 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301182 log.Fields{
1183 "ul_classifier": classifier,
1184 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001185 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301186 "intf-id": intfID,
1187 "onu-id": onuID,
1188 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301189
David K. Bainbridge794735f2020-02-11 21:01:37 -08001190 classifierProto, err := makeOpenOltClassifierField(classifier)
1191 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301192 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301193 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001194 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001195 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001196 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301197 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301198 }
1199
David K. Bainbridge794735f2020-02-11 21:01:37 -08001200 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001201 OnuId: int32(onuID),
1202 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001203 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001204 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001205 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001206 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001207 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301208 Classifier: classifierProto,
1209 Action: actionProto,
1210 Priority: int32(logicalFlow.Priority),
1211 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001212 PortNo: flowContext.portNo,
1213 TechProfileId: flowContext.tpID,
1214 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1215 PbitToGemport: flowContext.pbitToGem,
1216 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001217 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001218 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001219 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001220 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001221 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301222 log.Fields{
1223 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001224 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301225 "intf-id": intfID,
1226 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301227
David K. Bainbridge794735f2020-02-11 21:01:37 -08001228 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301229}
1230
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001231// addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001232func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1233 delete(flowContext.classifier, VlanVid)
1234 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001235}
1236
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001237// addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001238func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001239 intfID := flowContext.intfID
1240 onuID := flowContext.onuID
1241 uniID := flowContext.uniID
1242 logicalFlow := flowContext.logicalFlow
1243 classifier := flowContext.classifier
1244 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001245
Neha Sharma96b7bf22020-06-15 10:37:32 +00001246 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001247 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301248 return olterrors.NewErrNotFound("nni-interface-id",
1249 log.Fields{
1250 "classifier": classifier,
1251 "action": action,
1252 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001253 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001254 }
1255
1256 // Clear the action map
1257 for k := range action {
1258 delete(action, k)
1259 }
1260
1261 action[TrapToHost] = true
1262 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001263
yasin saplibddc2d72022-02-08 13:10:17 +00001264 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001265 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001266 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001267 return nil
yasin saplid0566272021-12-21 09:10:30 +00001268 } else if err != nil {
1269 logger.Errorw(ctx, "aborting-addUpstreamTrapFlow--flow-may-already-exist",
1270 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1271 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00001272 }
1273
Neha Sharma96b7bf22020-06-15 10:37:32 +00001274 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301275 log.Fields{
1276 "ul_classifier": classifier,
1277 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001278 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301279 "device-id": f.deviceHandler.device.Id,
1280 "intf-id": intfID,
1281 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001282
David K. Bainbridge794735f2020-02-11 21:01:37 -08001283 classifierProto, err := makeOpenOltClassifierField(classifier)
1284 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301285 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001286 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001287 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301288 log.Fields{
1289 "classifier": *classifierProto,
1290 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001291 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001292 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301293 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001294 }
1295
David K. Bainbridge794735f2020-02-11 21:01:37 -08001296 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001297 OnuId: int32(onuID),
1298 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001299 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001300 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001301 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001302 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001303 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001304 Classifier: classifierProto,
1305 Action: actionProto,
1306 Priority: int32(logicalFlow.Priority),
1307 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001308 PortNo: flowContext.portNo,
1309 TechProfileId: flowContext.tpID,
1310 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1311 PbitToGemport: flowContext.pbitToGem,
1312 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001313 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001314
David K. Bainbridge794735f2020-02-11 21:01:37 -08001315 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001316 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001317 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001318
David K. Bainbridge794735f2020-02-11 21:01:37 -08001319 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001320}
1321
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001322// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001323func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1324 intfID := flowContext.intfID
1325 onuID := flowContext.onuID
1326 uniID := flowContext.uniID
1327 portNo := flowContext.portNo
1328 allocID := flowContext.allocID
1329 gemPortID := flowContext.gemPortID
1330 logicalFlow := flowContext.logicalFlow
1331 classifier := flowContext.classifier
1332 action := flowContext.action
1333
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001334 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301335 log.Fields{
1336 "intf-id": intfID,
1337 "onu-id": onuID,
1338 "port-no": portNo,
1339 "alloc-id": allocID,
1340 "gemport-id": gemPortID,
1341 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001342 "flow": logicalFlow,
1343 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301344
1345 uplinkClassifier := make(map[string]interface{})
1346 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301347
manikkaraj kbf256be2019-03-25 00:13:48 +05301348 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001349 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001350 uplinkClassifier[PacketTagType] = SingleTag
1351 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001352 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301353 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001354 uplinkAction[TrapToHost] = true
yasin saplibddc2d72022-02-08 13:10:17 +00001355 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001356 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001357 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301358 "device-id": f.deviceHandler.device.Id,
1359 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001360 "intf-id": intfID,
1361 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001362 return nil
yasin saplid0566272021-12-21 09:10:30 +00001363 } else if err != nil {
1364 logger.Errorw(ctx, "aborting-addEthTypeBasedFlow--flow-may-already-exist",
1365 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1366 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301367 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301368 // Add Uplink EthType Flow
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001369 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301370 log.Fields{
1371 "ul_classifier": uplinkClassifier,
1372 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001373 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301374 "device-id": f.deviceHandler.device.Id,
1375 "intf-id": intfID,
1376 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301377
David K. Bainbridge794735f2020-02-11 21:01:37 -08001378 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1379 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301380 return olterrors.NewErrInvalidValue(log.Fields{
1381 "classifier": uplinkClassifier,
1382 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301383 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001384 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301385 log.Fields{
1386 "classifier": *classifierProto,
1387 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001388 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001389 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301390 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301391 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001392 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301393 log.Fields{
1394 "action": *actionProto,
1395 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001396 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301397 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301398 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001399 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301400 "action": action,
1401 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001402 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301403 }
1404
David K. Bainbridge794735f2020-02-11 21:01:37 -08001405 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001406 OnuId: int32(onuID),
1407 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001408 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001409 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001410 AllocId: int32(allocID),
1411 NetworkIntfId: int32(networkIntfID),
1412 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301413 Classifier: classifierProto,
1414 Action: actionProto,
1415 Priority: int32(logicalFlow.Priority),
1416 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001417 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001418 TechProfileId: flowContext.tpID,
1419 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1420 PbitToGemport: flowContext.pbitToGem,
1421 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001422 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001423 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001424 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001425 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001426 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301427 log.Fields{
1428 "device-id": f.deviceHandler.device.Id,
1429 "onu-id": onuID,
1430 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001431 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301432 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001433
David K. Bainbridge794735f2020-02-11 21:01:37 -08001434 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301435}
1436
David K. Bainbridge794735f2020-02-11 21:01:37 -08001437func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001438 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001439
1440 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1441 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1442 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001443 if vlanID != ReservedVlan {
1444 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001445 classifier.OVid = vid
1446 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301447 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07001448 // The classifierInfo[Metadata] is set for the following flows
1449 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
1450 // - Mcast flow that points to a group in the treatment
1451 // This value, when present and valid (not 0 and not 4096), is interpreted as below
1452 // - inner vid for a double tagged packet in the datapath flow
1453 // - outer vid for a single tagged packet in the datapath flow
1454 // - inner vid in the mcast flow that points to a group
David K. Bainbridge82efc492019-09-04 09:57:11 -07001455 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1456 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301457 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1458 // 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 +05301459 // 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 +05301460 // becomes the IVid.
1461 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1462 if vid != ReservedVlan {
1463 classifier.IVid = vid
1464 }
1465 } else {
1466 if vid != ReservedVlan {
1467 classifier.OVid = vid
1468 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001469 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301470 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301471 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001472 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301473 classifier.OPbits = vlanPcp
1474 } else {
1475 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301476 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001477 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1478 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1479 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1480 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001481 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001482 classifier.SrcMac, _ = classifierInfo[EthSrc].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001483 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1484 classifier.PktTagType = pktTagType
1485
1486 switch pktTagType {
1487 case SingleTag:
1488 case DoubleTag:
1489 case Untagged:
1490 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001491 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301492 }
1493 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001494 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301495}
1496
Akash Kankanala041a2122024-10-16 15:49:22 +05301497// nolint: unparam
1498// TODO: Improvise the function & remove the unparam lint, currently it is always returning 'nil' as error.
Gamze Abaka724d0852020-03-18 12:10:24 +00001499func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001500 var actionCmd openoltpb2.ActionCmd
1501 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301502 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001503 if _, ok := actionInfo[PopVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001504 // Pop outer vid
manikkaraj kbf256be2019-03-25 00:13:48 +05301505 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001506 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001507 // Remark inner pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001508 action.Cmd.RemarkInnerPbits = true
1509 action.IPbits = actionInfo[VlanPcp].(uint32)
1510 if _, ok := actionInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001511 // Remark inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001512 action.Cmd.TranslateInnerTag = true
1513 action.IVid = actionInfo[VlanVid].(uint32)
1514 }
1515 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001516 } else if _, ok := actionInfo[PushVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001517 // push outer vid
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001518 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301519 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001520 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001521 // translate outer pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001522 action.OPbits = actionInfo[VlanPcp].(uint32)
1523 action.Cmd.RemarkOuterPbits = true
1524 if _, ok := classifierInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001525 // translate inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001526 action.IVid = classifierInfo[VlanVid].(uint32)
1527 action.Cmd.TranslateInnerTag = true
1528 }
1529 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001530 } else if _, ok := actionInfo[TrapToHost]; ok {
1531 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001532 } else if _, ok := actionInfo[VlanVid]; ok {
1533 // Translate outer vid
1534 action.Cmd.TranslateOuterTag = true
1535 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301536 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301537 // When OLT is transparent to vlans no-action is valid.
1538 /*
1539 else {
1540 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1541 }
1542 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001543 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301544}
1545
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001546// getTPpath return the ETCD path for a given UNI port
yasin saplibddc2d72022-02-08 13:10:17 +00001547func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001548 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301549}
1550
Gamze Abakafee36392019-10-03 11:17:24 +00001551// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001552// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1553// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1554// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1555// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1556// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1557// because it was observed that if the ONU device was deleted too soon after the flows were
1558// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1559// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1560// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001561func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
yasin saplibddc2d72022-02-08 13:10:17 +00001562 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001563 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1564
Gamze Abakafee36392019-10-03 11:17:24 +00001565 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001566 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001567 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001568 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
yasin saplibddc2d72022-02-08 13:10:17 +00001569 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001570 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1571 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1572 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1573 log.Fields{
1574 "tp-id": tpID,
1575 "path": tpPath})
1576 }
1577 switch tpInstance := tpInst.(type) {
1578 case *tp_pb.TechProfileInstance:
1579 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1580 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1581 }
1582 // Force cleanup scheduler/queues -- end
1583
1584 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301585 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001586 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301587 // return err
1588 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001589 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001590 logger.Debugw(ctx, "tech-profile-instance-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "uniPortName": uniPortName, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001591 }
1592 return nil
1593}
1594
1595// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301596func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001597 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001598 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001599 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001600 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301601 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1602 log.Fields{
1603 "tp-id": tpID,
1604 "uni-port-name": uniPortName,
1605 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001606 }
1607 return nil
1608}
1609
David K. Bainbridge794735f2020-02-11 21:01:37 -08001610func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001611 var intfID uint32
1612 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1613 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1614 */
1615 if deviceFlow.AccessIntfId != -1 {
1616 intfID = uint32(deviceFlow.AccessIntfId)
1617 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001618 // We need to log the valid interface ID.
1619 // 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 +00001620 intfID = uint32(deviceFlow.NetworkIntfId)
1621 }
1622
Neha Sharma96b7bf22020-06-15 10:37:32 +00001623 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301624 "flow": *deviceFlow,
1625 "device-id": f.deviceHandler.device.Id,
1626 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001627 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001628
1629 st, _ := status.FromError(err)
1630 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001631 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001632 "err": err,
1633 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301634 "device-id": f.deviceHandler.device.Id,
1635 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001636 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301637 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001638
1639 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001640 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301641 log.Fields{"err": err,
1642 "device-flow": deviceFlow,
1643 "device-id": f.deviceHandler.device.Id,
1644 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001645 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001646 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001647 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301648 log.Fields{
1649 "flow": *deviceFlow,
1650 "device-id": f.deviceHandler.device.Id,
1651 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001652
yasin saplid0566272021-12-21 09:10:30 +00001653 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1654 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1655 return err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001656 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001657 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001658}
1659
Neha Sharma96b7bf22020-06-15 10:37:32 +00001660func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1661 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301662 log.Fields{
1663 "flow": *deviceFlow,
1664 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001665 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001666 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001667 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001668 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301669 log.Fields{
1670 "err": err,
1671 "deviceFlow": deviceFlow,
1672 "device-id": f.deviceHandler.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +05301673 // Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001674 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001675 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001676 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001677 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001678 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001679 "of-flow-id": ofFlowID,
1680 "flow": *deviceFlow,
1681 "device-id": f.deviceHandler.device.Id,
1682 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001683 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301684}
1685
David K. Bainbridge794735f2020-02-11 21:01:37 -08001686func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001687 classifierInfo := make(map[string]interface{})
1688 actionInfo := make(map[string]interface{})
1689
1690 classifierInfo[EthType] = uint32(LldpEthType)
1691 classifierInfo[PacketTagType] = Untagged
1692 actionInfo[TrapToHost] = true
1693
1694 // LLDP flow is installed to trap LLDP packets on the NNI port.
1695 // We manage flow_id resource pool on per PON port basis.
1696 // Since this situation is tricky, as a hack, we pass the NNI port
1697 // index (network_intf_id) as PON port Index for the flow_id resource
1698 // pool. Also, there is no ONU Id available for trapping LLDP packets
1699 // on NNI port, use onu_id as -1 (invalid)
1700 // ****************** CAVEAT *******************
1701 // This logic works if the NNI Port Id falls within the same valid
1702 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1703 // we need to have a re-look at this.
1704 // *********************************************
1705
1706 var onuID = -1
1707 var uniID = -1
1708 var gemPortID = -1
1709
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001710 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001711 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301712 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001713 }
yasin saplibddc2d72022-02-08 13:10:17 +00001714 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001715 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001716 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001717 return nil
yasin saplid0566272021-12-21 09:10:30 +00001718 } else if err != nil {
1719 logger.Errorw(ctx, "aborting-addLLDPFlow--flow-may-already-exist",
1720 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
1721 return err
Humera Kouser94d7a842019-08-25 19:04:32 -04001722 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001723
David K. Bainbridge794735f2020-02-11 21:01:37 -08001724 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1725 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301726 return olterrors.NewErrInvalidValue(
1727 log.Fields{
1728 "classifier": classifierInfo,
1729 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001730 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001731 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301732 log.Fields{
1733 "classifier": *classifierProto,
1734 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001735 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001736 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301737 return olterrors.NewErrInvalidValue(
1738 log.Fields{
1739 "action": actionInfo,
1740 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001741 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001742 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301743 log.Fields{
1744 "action": *actionProto,
1745 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001746
1747 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1748 OnuId: int32(onuID), // OnuId not required
1749 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001750 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001751 FlowType: Downstream,
1752 NetworkIntfId: int32(networkInterfaceID),
1753 GemportId: int32(gemPortID),
1754 Classifier: classifierProto,
1755 Action: actionProto,
1756 Priority: int32(flow.Priority),
1757 Cookie: flow.Cookie,
1758 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001759 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001760 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301761 log.Fields{
1762 "flow": downstreamflow,
1763 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001764 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001765 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301766 log.Fields{
1767 "device-id": f.deviceHandler.device.Id,
1768 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001769 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001770
David K. Bainbridge794735f2020-02-11 21:01:37 -08001771 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301772}
1773
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001774func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1775 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001776}
1777
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001778// getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001779func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001780 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1781 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1782 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001783 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301784 log.Fields{
1785 "intf-id": intfID,
1786 "onu-id": onuID,
1787 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001788 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001789 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301790 return nil, olterrors.NewErrNotFound("onu-child-device",
1791 log.Fields{
1792 "onu-id": onuID,
1793 "intf-id": intfID,
1794 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001795 }
khenaidoo106c61a2021-08-11 18:05:46 -04001796 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 +05301797 // better to ad the device to cache here.
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001798 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1799 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001800 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301801 log.Fields{
1802 "intf-id": intfID,
1803 "onu-id": onuID,
1804 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001805 }
1806
1807 return onuDev.(*OnuDevice), nil
1808}
1809
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001810// getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001811func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1812 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301813 log.Fields{
1814 "pon-port": intfID,
1815 "onu-id": onuID,
1816 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001817 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001818 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001819 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301820 return nil, olterrors.NewErrNotFound("onu",
1821 log.Fields{
1822 "interface-id": parentPortNo,
1823 "onu-id": onuID,
1824 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001825 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301826 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001827 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301828 log.Fields{
1829 "device-id": f.deviceHandler.device.Id,
1830 "child_device_id": onuDevice.Id,
1831 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301832 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301833}
1834
Neha Sharma96b7bf22020-06-15 10:37:32 +00001835func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1836 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301837 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001838 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301839 log.Fields{
1840 "intf-id": intfID,
1841 "onu-id": onuID,
1842 "uni-id": uniID,
1843 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001844 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301845 }
1846
khenaidoodc2116e2021-10-19 17:33:19 -04001847 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001848 DeviceId: onuDev.deviceID,
1849 UniId: uniID,
1850 TpInstancePath: tpPath,
1851 GemPortId: gemPortID,
1852 }
1853 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1854
1855 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301856 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1857 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001858 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1859 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301860 "onu-id": onuDev.deviceID,
1861 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001862 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301863 }
khenaidoo106c61a2021-08-11 18:05:46 -04001864
Neha Sharma96b7bf22020-06-15 10:37:32 +00001865 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301866 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001867 "msg": delGemPortMsg,
1868 "from-adapter": f.deviceHandler.device.Type,
1869 "to-adapter": onuDev.deviceType,
1870 "device-id": f.deviceHandler.device.Id,
1871 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301872 return nil
1873}
1874
Neha Sharma96b7bf22020-06-15 10:37:32 +00001875func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1876 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301877 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001878 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301879 log.Fields{
1880 "intf-id": intfID,
1881 "onu-id": onuID,
1882 "uni-id": uniID,
1883 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001884 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301885 }
1886
khenaidoodc2116e2021-10-19 17:33:19 -04001887 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001888 DeviceId: onuDev.deviceID,
1889 UniId: uniID,
1890 TpInstancePath: tpPath,
1891 AllocId: allocID,
1892 }
1893
Neha Sharma96b7bf22020-06-15 10:37:32 +00001894 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301895 log.Fields{
1896 "msg": *delTcontMsg,
1897 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001898
1899 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301900 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1901 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001902 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1903 "to-adapter": onuDev.adapterEndpoint,
1904 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301905 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001906 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301907 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001908 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301909 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001910 "msg": delTcontMsg,
1911 "device-id": f.deviceHandler.device.Id,
1912 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301913 return nil
1914}
1915
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001916// clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001917// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001918func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05301919 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool, nniIntfID uint32) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001920 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001921
Girish Gowdraa482f272021-03-24 23:04:19 -07001922 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
yasin saplibddc2d72022-02-08 13:10:17 +00001923 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001924 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1925 log.Fields{
1926 "tpPath": tpPath,
1927 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001928
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001929 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001930 if err != nil || techprofileInst == nil {
1931 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1932 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1933 if childDevice == nil {
1934 // happens when subscriber un-provision is immediately followed by child device delete
1935 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1936 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1937 return nil
1938 }
Elia Battiston2aaf4342022-02-07 15:16:38 +01001939 // If the tech profile is not found, since we want to delete it, there is no need to throw an error
1940 _ = olterrors.NewErrNotFound("tech-profile-in-kv-store",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001941 log.Fields{
1942 "tp-id": tpID,
Elia Battiston2aaf4342022-02-07 15:16:38 +01001943 "path": tpPath}, err).Log()
1944 return nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001945 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001946
1947 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001948 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001949 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001950 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1951 gemPortID := gemPort.GemportId
Girish Gowdrab4c33302022-03-18 15:07:38 -07001952 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, gemPortID)
1953 if err != nil {
1954 return err
1955 }
1956 used := false
1957 for _, id := range flowIDs {
1958 if flowID != id {
1959 used = true
1960 break
yasin sapli9e4c5092022-02-01 13:52:33 +00001961 }
Girish Gowdrab4c33302022-03-18 15:07:38 -07001962 }
1963 if used {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001964 for i, flowIDinMap := range flowIDs {
1965 if flowIDinMap == flowID {
1966 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
yasin saplibddc2d72022-02-08 13:10:17 +00001967 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, gemPortID, flowIDs); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001968 return err
1969 }
1970 break
1971 }
1972 }
1973 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1974 log.Fields{
1975 "gemport-id": gemPortID,
1976 "usedByFlows": flowIDs,
1977 "currentFlow": flowID,
1978 "device-id": f.deviceHandler.device.Id})
1979 allGemPortsFree = false
1980 }
1981 }
1982 if !allGemPortsFree {
1983 return nil
1984 }
1985 }
1986
1987 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 -08001988
1989 // 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 +00001990 switch techprofileInst := techprofileInst.(type) {
1991 case *tp_pb.TechProfileInstance:
Girish Gowdraf3728b12022-02-02 21:46:51 -08001992 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1993 gemPortID := gemPort.GemportId
yasin saplibddc2d72022-02-08 13:10:17 +00001994 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, uint32(onuID), gemPortID) // ignore error and proceed.
Girish Gowdraf3728b12022-02-02 21:46:51 -08001995
yasin saplibddc2d72022-02-08 13:10:17 +00001996 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, gemPortID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08001997 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
1998 log.Fields{
1999 "err": err,
2000 "intf": intfID,
2001 "onu-id": onuID,
2002 "uni-id": uniID,
2003 "device-id": f.deviceHandler.device.Id,
2004 "gemport-id": gemPortID})
2005 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002006 }
2007 // Remove queues at OLT in upstream and downstream direction
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302008 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 +05302009 if err := f.RemoveQueues(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002010 logger.Warn(ctx, err)
2011 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302012 schedQ.direction = tp_pb.Direction_DOWNSTREAM
2013 if err := f.RemoveQueues(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002014 logger.Warn(ctx, err)
2015 }
2016 }
2017
2018 switch techprofileInst := techprofileInst.(type) {
2019 case *tp_pb.TechProfileInstance:
2020 // 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 +05302021 schedQ := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2022 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQ)
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002023 if !allocExists {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002024 // all alloc object references removed, remove upstream scheduler
yasin saplibddc2d72022-02-08 13:10:17 +00002025 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302026 if err := f.RemoveScheduler(ctx, schedQ); err != nil {
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002027 logger.Warn(ctx, err)
2028 }
2029 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002030 // remove alloc id from resource pool by setting the 'freeFromResourcePool' to true
yasin saplibddc2d72022-02-08 13:10:17 +00002031 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, true)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002032 } else {
2033 // just remove meter reference for the upstream direction for the current pon/onu/uni
2034 // 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 +05302035 if err := f.removeMeterReference(ctx, "upstream", schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002036 return err
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002037 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002038 // setting 'freeFromResourcePool' to false in resourceMgr.FreeAllocID will only remove alloc-id data for the given pon/onu/uni
2039 // but still preserve it on the resource pool.
yasin saplibddc2d72022-02-08 13:10:17 +00002040 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, false)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002041 }
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002042
Girish Gowdraf3728b12022-02-02 21:46:51 -08002043 // 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 +05302044 schedQ.direction = tp_pb.Direction_DOWNSTREAM
yasin saplibddc2d72022-02-08 13:10:17 +00002045 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302046 if err := f.RemoveScheduler(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002047 logger.Warn(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002048 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002049 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002050 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002051 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002052 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002053 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302054 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002055 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302056 "onu-id": onuID,
2057 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002058 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002059 "alloc-id": techprofileInst.AllocId,
2060 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002061 }
yasin saplibddc2d72022-02-08 13:10:17 +00002062 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.AllocId, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302063 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
2064 logger.Warn(ctx, err)
2065 }
2066 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2067 logger.Warn(ctx, err)
2068 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002069 default:
2070 logger.Errorw(ctx, "error-unknown-tech",
2071 log.Fields{
2072 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002073 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002074
2075 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
2076 switch techprofileInst := techprofileInst.(type) {
2077 case *tp_pb.TechProfileInstance:
2078 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2079 // Delete the gem port on the ONU.
2080 if sendDeleteGemRequest {
2081 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId, tpPath); err != nil {
2082 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2083 log.Fields{
2084 "err": err,
2085 "intfID": intfID,
2086 "onu-id": onuID,
2087 "uni-id": uniID,
2088 "device-id": f.deviceHandler.device.Id,
2089 "gemport-id": gemPort.GemportId})
2090 }
yasin saplibddc2d72022-02-08 13:10:17 +00002091 f.resourceMgr.FreeGemPortID(ctx, uint32(onuID), uint32(uniID), gemPort.GemportId)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002092 }
2093 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302094 // Delete the tp instance and the techprofileid for onu at the end
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302095 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2096 logger.Warn(ctx, err)
2097 }
2098 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
2099 logger.Warn(ctx, err)
2100 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002101 }
2102
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302103 return nil
2104}
2105
David K. Bainbridge794735f2020-02-11 21:01:37 -08002106// nolint: gocyclo
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302107func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string, nni_port uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002108 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302109 log.Fields{
2110 "flowDirection": flowDirection,
2111 "flow": *flow,
2112 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002113
2114 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002115 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002116 }
2117
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302118 var ethType, ipProto, inPort uint32
2119 for _, field := range flows.GetOfbFields(flow) {
mgouda86543582025-10-29 20:58:16 +05302120 switch field.Type {
2121 case flows.IP_PROTO:
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302122 ipProto = field.GetIpProto()
2123 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"ipProto": ipProto})
mgouda86543582025-10-29 20:58:16 +05302124 case flows.ETH_TYPE:
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302125 ethType = field.GetEthType()
2126 logger.Debugw(ctx, "field-type-eth-type", log.Fields{"ethType": ethType})
mgouda86543582025-10-29 20:58:16 +05302127 case flows.IN_PORT:
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302128 inPort = field.GetPort()
2129 logger.Debugw(ctx, "field-type-in-port", log.Fields{"inPort": inPort})
2130 }
2131 }
2132 portType := plt.IntfIDToPortTypeName(inPort)
2133 if (ethType == uint32(LldpEthType) || ipProto == uint32(IPProtoDhcp) || ipProto == uint32(IgmpProto)) &&
2134 (portType == voltha.Port_ETHERNET_NNI) {
2135 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: -1, OnuId: -1, UniId: -1, TechProfileId: 0, FlowType: Downstream}
2136 logger.Debugw(ctx, "nni-trap-flow-to-be-deleted", log.Fields{"flow": flow})
2137 return f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id)
2138 // No more processing needed for trap from nni flows.
2139 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302140
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302141 portNum, Intf, onu, uni, _, _, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302142 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002143 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002144 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302145 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002146 onuID := int32(onu)
2147 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002148 tpID, err := getTpIDFromFlow(ctx, flow)
2149 if err != nil {
2150 return olterrors.NewErrNotFound("tp-id",
2151 log.Fields{
2152 "flow": flow,
2153 "intf-id": Intf,
2154 "onu-id": onuID,
2155 "uni-id": uniID,
2156 "device-id": f.deviceHandler.device.Id}, err)
2157 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302158
Neha Sharma96b7bf22020-06-15 10:37:32 +00002159 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302160 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002161 "flow-id": flow.Id,
2162 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302163 "onu-id": onuID,
2164 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302165
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002166 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2167 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002168 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2169 return err
2170 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002171
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302172 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true, nni_port); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002173 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2174 "flow-id": flow.Id,
2175 "device-id": f.deviceHandler.device.Id,
2176 "onu-id": onuID,
2177 "intf": Intf,
2178 "err": err,
2179 })
2180 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302181 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002182
Girish Gowdra82c80982021-03-26 16:22:02 -07002183 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
yasin saplibddc2d72022-02-08 13:10:17 +00002184 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, uint32(onuID), uint32(uniID), tpID, false); err != nil {
Girish Gowdra82c80982021-03-26 16:22:02 -07002185 return err
2186 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002187 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002188}
2189
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002190// RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002191func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Matteo Scandolof16389e2021-05-18 00:47:08 +00002192 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302193 var direction string
2194 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002195
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302196 for _, action := range flows.GetActions(flow) {
2197 if action.Type == flows.OUTPUT {
2198 if out := action.GetOutput(); out != nil {
2199 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002200 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302201 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002202 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002203 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002204 }
2205 }
2206 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002207
2208 if flows.HasGroup(flow) {
2209 direction = Multicast
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002210 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302211 direction = Upstream
2212 } else {
2213 direction = Downstream
2214 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302215
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302216 var nni_port uint32
2217 if direction == Upstream {
2218 if !plt.IsControllerBoundFlow(actionInfo[Output].(uint32)) {
2219 nni_port = actionInfo[Output].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2220 }
2221 } else {
2222 classifierInfo := make(map[string]interface{})
2223 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
2224 nni_port = classifierInfo[InPort].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2225 }
2226
Girish Gowdracefae192020-03-19 18:14:10 -07002227 // Serialize flow removes on a per subscriber basis
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302228 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction, nni_port)
Girish Gowdracefae192020-03-19 18:14:10 -07002229
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002230 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002231}
2232
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002233// isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
Esin Karamanae41e2b2019-12-17 18:13:13 +00002234func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002235 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002236 if ethType, ok := classifierInfo[EthType]; ok {
2237 if ethType.(uint32) == IPv4EthType {
2238 if ipProto, ok := classifierInfo[IPProto]; ok {
2239 if ipProto.(uint32) == IgmpProto {
2240 return true
2241 }
2242 }
2243 }
2244 }
2245 }
2246 return false
2247}
2248
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002249// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002250func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002251 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2252 // The device itself is going to be reset as part of deletion. So nothing to be done.
2253 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2254 return nil
2255 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002256 // Step1 : Fill flowControlBlock
2257 // Step2 : Push the flowControlBlock to ONU channel
2258 // Step3 : Wait on response channel for response
2259 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002260 startTime := time.Now()
2261 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002262 errChan := make(chan error)
2263 flowCb := flowControlBlock{
2264 ctx: ctx,
2265 addFlow: addFlow,
2266 flow: flow,
2267 flowMetadata: flowMetadata,
2268 errChan: &errChan,
2269 }
2270 inPort, outPort := getPorts(flow)
2271 var onuID uint32
2272 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002273 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002274 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002275 if f.flowHandlerRoutineActive[onuID] {
2276 // inPort or outPort is InvalidPort for trap-from-nni flows.
2277 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2278 // Send the flowCb on the ONU flow channel
2279 f.incomingFlows[onuID] <- flowCb
2280 // Wait on the channel for flow handlers return value
2281 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002282 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002283 return err
2284 }
2285 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2286 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002287}
2288
2289// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2290// 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 -07002291func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002292 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002293 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002294 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002295 // block on the channel to receive an incoming flow
2296 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002297 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002298 if flowCb.addFlow {
2299 logger.Info(flowCb.ctx, "adding-flow-start")
2300 startTime := time.Now()
2301 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2302 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2303 // Pass the return value over the return channel
2304 *flowCb.errChan <- err
2305 } else {
2306 logger.Info(flowCb.ctx, "removing-flow-start")
2307 startTime := time.Now()
2308 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2309 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2310 // Pass the return value over the return channel
2311 *flowCb.errChan <- err
2312 }
2313 case <-stopHandler:
2314 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2315 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002316 }
2317 }
2318}
2319
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002320// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002321func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002322 for i, v := range f.stopFlowHandlerRoutine {
2323 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002324 select {
2325 case v <- true:
2326 case <-time.After(time.Second * 5):
2327 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2328 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002329 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002330 f.stopFlowHandlerRoutine[i] = nil
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002331 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002332 f.stopFlowHandlerRoutine = nil
2333
2334 if f.incomingFlows != nil {
2335 for k := range f.incomingFlows {
2336 if f.incomingFlows[k] != nil {
2337 f.incomingFlows[k] = nil
2338 }
2339 }
2340 f.incomingFlows = nil
2341 }
2342
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002343 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002344 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2345}
2346
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002347// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302348// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002349func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002350 classifierInfo := make(map[string]interface{})
2351 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002352 var UsMeterID uint32
2353 var DsMeterID uint32
2354
Neha Sharma96b7bf22020-06-15 10:37:32 +00002355 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302356 log.Fields{
2357 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002358 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002359 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002360
Neha Sharma96b7bf22020-06-15 10:37:32 +00002361 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002362 if err != nil {
2363 // Error logging is already done in the called function
2364 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002365 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302366 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002367
Esin Karamanccb714b2019-11-29 15:02:06 +00002368 if flows.HasGroup(flow) {
2369 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002370 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002371 }
2372
manikkaraj k17652a72019-05-06 09:06:36 -04002373 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002374 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002375 if err != nil {
2376 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002377 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002378 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002379
Neha Sharma96b7bf22020-06-15 10:37:32 +00002380 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302381 log.Fields{
2382 "classifierinfo_inport": classifierInfo[InPort],
2383 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002384 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002385
Humera Kouser94d7a842019-08-25 19:04:32 -04002386 if ethType, ok := classifierInfo[EthType]; ok {
2387 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002388 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002389 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002390 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002391 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002392 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002393 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2394 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2395 }
2396 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002397 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002398 if ipProto, ok := classifierInfo[IPProto]; ok {
2399 if ipProto.(uint32) == IPProtoDhcp {
2400 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302401 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002402 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002403 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002404 }
2405 }
2406 }
2407 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002408 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002409 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002410 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002411 }
A R Karthick1f85b802019-10-11 05:06:05 +00002412
yasin saplibddc2d72022-02-08 13:10:17 +00002413 f.resourceMgr.AddUniPortToOnuInfo(ctx, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002414
Girish Gowdra6071f382021-12-14 12:52:04 +05302415 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002416 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302417 return olterrors.NewErrNotFound("tpid-for-flow",
2418 log.Fields{
2419 "flow": flow,
2420 "intf-id": IntfID,
2421 "onu-id": onuID,
2422 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002423 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002424 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302425 log.Fields{
Girish Gowdra6071f382021-12-14 12:52:04 +05302426 "tp-id": tpID,
Shrey Baid26912972020-04-16 21:02:31 +05302427 "intf-id": intfID,
2428 "onu-id": onuID,
2429 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002430 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002431 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002432 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302433 if err := f.validateMeter(ctx, Upstream, UsMeterID, intfID, onuID, uniID, tpID); err != nil {
2434 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2435 return err
2436 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002437 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002438 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002439 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302440 if err := f.validateMeter(ctx, Downstream, DsMeterID, intfID, onuID, uniID, tpID); err != nil {
2441 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2442 return err
2443 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002444 }
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302445
2446 var nni_port uint32
2447 if plt.IsUpstream(actionInfo[Output].(uint32)) {
2448 if !plt.IsControllerBoundFlow(actionInfo[Output].(uint32)) {
2449 nni_port = actionInfo[Output].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2450 }
2451 } else {
2452 nni_port = classifierInfo[InPort].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2453 }
2454
2455 return f.processAddFlow(ctx, intfID, nni_port, onuID, uniID, portNo, classifierInfo, actionInfo, flow, tpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002456}
Girish Gowdra3d633032019-12-10 16:37:05 +05302457
Esin Karamanccb714b2019-11-29 15:02:06 +00002458// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002459func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302460 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002461 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302462 "classifier-info": classifierInfo,
2463 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002464
Esin Karaman65409d82020-03-18 10:58:18 +00002465 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002466 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002467 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002468 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002469
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002470 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002471
David K. Bainbridge794735f2020-02-11 21:01:37 -08002472 onuID := NoneOnuID
Esin Karamanccb714b2019-11-29 15:02:06 +00002473
yasin saplibddc2d72022-02-08 13:10:17 +00002474 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002475 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002476 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002477 return nil
yasin saplid0566272021-12-21 09:10:30 +00002478 } else if err != nil {
2479 logger.Errorw(ctx, "aborting-handleFlowWithGroup--flow-may-already-exist",
2480 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
2481 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00002482 }
yasin saplid0566272021-12-21 09:10:30 +00002483
David K. Bainbridge794735f2020-02-11 21:01:37 -08002484 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2485 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002486 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002487 }
2488 groupID := actionInfo[GroupID].(uint32)
2489 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002490 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002491 FlowType: Multicast,
2492 NetworkIntfId: int32(networkInterfaceID),
2493 GroupId: groupID,
2494 Classifier: classifierProto,
2495 Priority: int32(flow.Priority),
2496 Cookie: flow.Cookie}
2497
Kent Hagermane6ff1012020-07-14 15:07:53 -04002498 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002499 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002500 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002501 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
Akash Kankanala041a2122024-10-16 15:49:22 +05302502 // get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002503 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302504 // calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002505 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002506 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002507 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302508 // cached group can be removed now
Kent Hagermane6ff1012020-07-14 15:07:53 -04002509 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002510 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002511 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002512 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002513
David K. Bainbridge794735f2020-02-11 21:01:37 -08002514 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002515}
2516
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002517// 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 +00002518func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2519 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002520 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002521 if err != nil {
2522 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2523 }
2524 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002525 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002526
2527 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2528 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002529}
2530
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002531// sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002532func (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 +00002533 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302534 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002535 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302536 log.Fields{
2537 "intf-id": intfID,
2538 "onu-id": onuID,
2539 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002540 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302541 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002542 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002543
yasin saplibddc2d72022-02-08 13:10:17 +00002544 tpPath := f.getTPpath(ctx, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002545 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002546 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002547 UniId: uniID,
2548 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002549 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002550 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002551 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002552
2553 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2554 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302555 return olterrors.NewErrCommunication("send-techprofile-download-request",
2556 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002557 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302558 "to-adapter": onuDev.deviceType,
2559 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002560 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002561 }
nikesh.krishnan81ec7442023-10-31 17:19:34 +05302562 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpid": TpID})
Manikkaraj k884c1242019-04-11 16:26:42 +05302563 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302564}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002565
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002566// GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302567func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002568 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002569
mgouda86543582025-10-29 20:58:16 +05302570 switch packetIn.IntfType {
2571 case "pon":
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002572 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002573 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002574 onuID, uniID := packetIn.OnuId, packetIn.UniId
2575 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 +00002576
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002577 if packetIn.PortNo != 0 {
2578 logicalPortNum = packetIn.PortNo
2579 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002580 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002581 }
2582 // 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 +00002583 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
mgouda86543582025-10-29 20:58:16 +05302584 case "nni":
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002585 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002586 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002587
2588 if logger.V(log.DebugLevel) {
2589 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2590 log.Fields{
2591 "logical-port-num": logicalPortNum,
2592 "intf-type": packetIn.IntfType,
2593 "packet": hex.EncodeToString(packetIn.Pkt),
2594 })
2595 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002596 return logicalPortNum, nil
2597}
2598
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002599// GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002600func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002601 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002602
2603 ctag, priority, err := getCTagFromPacket(ctx, packet)
2604 if err != nil {
2605 return 0, err
2606 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302607
Esin Karaman7fb80c22020-07-16 14:23:33 +00002608 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002609 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002610 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002611 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002612 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302613 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002614 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302615 log.Fields{
2616 "pktinkey": pktInkey,
2617 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002618
2619 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002620 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302621 // 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 +00002622 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302623 if err == nil {
2624 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002625 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302626 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002627 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002628 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302629 log.Fields{
2630 "pktinkey": pktInkey,
2631 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302632 return gemPortID, nil
2633 }
2634 }
Shrey Baid26912972020-04-16 21:02:31 +05302635 return uint32(0), olterrors.NewErrNotFound("gem-port",
2636 log.Fields{
2637 "pktinkey": pktInkey,
2638 "gem": gemPortID}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002639}
2640
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002641func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2642 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002643 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002644 classifier[PacketTagType] = DoubleTag
2645 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002646 /* We manage flowId resource pool on per PON port basis.
2647 Since this situation is tricky, as a hack, we pass the NNI port
2648 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002649 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002650 on NNI port, use onu_id as -1 (invalid)
2651 ****************** CAVEAT *******************
2652 This logic works if the NNI Port Id falls within the same valid
2653 range of PON Port Ids. If this doesn't work for some OLT Vendor
2654 we need to have a re-look at this.
2655 *********************************************
2656 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002657 onuID := -1
2658 uniID := -1
2659 gemPortID := -1
2660 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002661 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302662 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302663 return olterrors.NewErrNotFound("nni-intreface-id",
2664 log.Fields{
2665 "classifier": classifier,
2666 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002667 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302668 }
2669
yasin saplibddc2d72022-02-08 13:10:17 +00002670 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002671 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002672 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002673 return nil
yasin saplid0566272021-12-21 09:10:30 +00002674 } else if err != nil {
2675 logger.Errorw(ctx, "aborting-addTrapFlowOnNNI--flow-may-already-exist",
2676 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2677 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002678 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002679
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002680 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2681 log.Fields{
2682 "classifier": classifier,
2683 "action": action,
2684 "flowId": logicalFlow.Id,
2685 "intf-id": networkInterfaceID})
2686
David K. Bainbridge794735f2020-02-11 21:01:37 -08002687 classifierProto, err := makeOpenOltClassifierField(classifier)
2688 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002689 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002690 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002691 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002692 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002693 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002694 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002695 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002696 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002697 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2698 OnuId: int32(onuID), // OnuId not required
2699 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002700 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002701 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002702 AllocId: int32(allocID), // AllocId not used
2703 NetworkIntfId: int32(networkInterfaceID),
2704 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002705 Classifier: classifierProto,
2706 Action: actionProto,
2707 Priority: int32(logicalFlow.Priority),
2708 Cookie: logicalFlow.Cookie,
2709 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002710 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002711 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002712 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002713 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002714 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002715}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002716
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002717// getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
Esin Karamanae41e2b2019-12-17 18:13:13 +00002718func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2719 var packetType string
2720 ovid, ivid := false, false
2721 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2722 vid := vlanID & VlanvIDMask
2723 if vid != ReservedVlan {
2724 ovid = true
2725 }
2726 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07002727
2728 // The classifierInfo[Metadata] is set for the following flows
2729 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
2730 // - Mcast flow that points to a group in the action/treatment
2731 // This value, when present and valid (not 0 and not 4096), is interpreted as below
2732 // - inner vid for a double tagged packet in the datapath flow
2733 // - outer vid for a single tagged packet in the datapath flow
2734 // - inner vid in the mcast flow that points to a group
2735
2736 // It is to be noted though that for DT FTTH downstream table0 flow, the classifierInfo[Metadata] is absent.
2737 // And consequently the ivid is not set to true. This will result in packetType being set to singleTag which is not true
2738 // Interestingly enough, this function `getPacketTypeFromClassifiers` is called only by Mcast flow handlers and
2739 // 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 +00002740 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2741 vid := uint32(metadata)
2742 if vid != ReservedVlan {
2743 ivid = true
2744 }
2745 }
2746 if ovid && ivid {
2747 packetType = DoubleTag
2748 } else if !ovid && !ivid {
2749 packetType = Untagged
2750 } else {
2751 packetType = SingleTag
2752 }
2753 return packetType
2754}
2755
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002756// addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002757func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002758 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002759 action := make(map[string]interface{})
2760 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2761 action[TrapToHost] = true
2762 /* We manage flowId resource pool on per PON port basis.
2763 Since this situation is tricky, as a hack, we pass the NNI port
2764 index (network_intf_id) as PON port Index for the flowId resource
2765 pool. Also, there is no ONU Id available for trapping packets
2766 on NNI port, use onu_id as -1 (invalid)
2767 ****************** CAVEAT *******************
2768 This logic works if the NNI Port Id falls within the same valid
2769 range of PON Port Ids. If this doesn't work for some OLT Vendor
2770 we need to have a re-look at this.
2771 *********************************************
2772 */
2773 onuID := -1
2774 uniID := -1
2775 gemPortID := -1
2776 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002777 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002778 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302779 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002780 "classifier": classifier,
2781 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002782 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002783 }
yasin saplibddc2d72022-02-08 13:10:17 +00002784 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002785 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002786 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002787 return nil
yasin saplid0566272021-12-21 09:10:30 +00002788 } else if err != nil {
2789 logger.Errorw(ctx, "aborting-addIgmpTrapFlowOnNNI--flow-may-already-exist",
2790 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2791 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002792 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002793
David K. Bainbridge794735f2020-02-11 21:01:37 -08002794 classifierProto, err := makeOpenOltClassifierField(classifier)
2795 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002796 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002797 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002798 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002799 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002800 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002801 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002802 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002803 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002804 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2805 OnuId: int32(onuID), // OnuId not required
2806 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002807 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002808 FlowType: Downstream,
2809 AllocId: int32(allocID), // AllocId not used
2810 NetworkIntfId: int32(networkInterfaceID),
2811 GemportId: int32(gemPortID), // GemportId not used
2812 Classifier: classifierProto,
2813 Action: actionProto,
2814 Priority: int32(logicalFlow.Priority),
2815 Cookie: logicalFlow.Cookie,
2816 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002817 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002818 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002819 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002820 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002821
David K. Bainbridge794735f2020-02-11 21:01:37 -08002822 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002823}
2824
salmansiddiqui7ac62132019-08-22 03:58:50 +00002825func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2826 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302827 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002828 }
mgouda86543582025-10-29 20:58:16 +05302829 switch Dir {
2830 case tp_pb.Direction_UPSTREAM:
salmansiddiqui7ac62132019-08-22 03:58:50 +00002831 return "upstream", nil
mgouda86543582025-10-29 20:58:16 +05302832 case tp_pb.Direction_DOWNSTREAM:
salmansiddiqui7ac62132019-08-22 03:58:50 +00002833 return "downstream", nil
2834 }
2835 return "", nil
2836}
2837
Kent Hagermane6ff1012020-07-14 15:07:53 -04002838// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302839func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002840 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002841 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002842 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002843 intfID := args[IntfID]
2844 onuID := args[OnuID]
2845 uniID := args[UniID]
2846 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002847 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002848 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002849 gemToAes := make(map[uint32]bool)
2850
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002851 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002852 var direction = tp_pb.Direction_UPSTREAM
2853 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002854 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002855 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002856 attributes = TpInst.UpstreamGemPortAttributeList
2857 } else {
2858 attributes = TpInst.DownstreamGemPortAttributeList
2859 direction = tp_pb.Direction_DOWNSTREAM
2860 }
2861 default:
2862 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002863 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002864 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002865
2866 if len(gemPorts) == 1 {
2867 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002868 gemPortID = gemPorts[0]
2869 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002870 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2871 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002872 pBitMap := attributes[idx].PbitMap
2873 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2874 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2875 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002876 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002877 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2878 if pbitSet == pbit1 {
2879 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2880 pbitToGem[pcp] = gemID
2881 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002882 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002883 }
2884 }
2885 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002886 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2887 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2888 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002889 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002890 }
2891
Akash Kankanala041a2122024-10-16 15:49:22 +05302892 flowContext := &flowContext{classifierInfo, actionInfo, flow, pbitToGem, gemToAes, intfID, onuID, uniID, portNo, allocID, gemPortID, tpID}
Gamze Abaka7650be62021-02-26 10:50:36 +00002893
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302894 var nni_port uint32
2895 if plt.IsUpstream(actionInfo[Output].(uint32)) {
2896 if !plt.IsControllerBoundFlow(actionInfo[Output].(uint32)) {
2897 nni_port = actionInfo[Output].(uint32) & 0x1f // convert e.g. 16777220 to port 4 (starting with 0)
2898 }
2899 } else {
2900 nni_port = classifierInfo[InPort].(uint32) & 0x1f // convert e.g. 16777220 to port 4 (starting with 0)
2901 }
2902
salmansiddiqui7ac62132019-08-22 03:58:50 +00002903 if ipProto, ok := classifierInfo[IPProto]; ok {
mgouda86543582025-10-29 20:58:16 +05302904 switch ipProto.(uint32) {
2905 case IPProtoDhcp:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002906 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002907 "tp-id": tpID,
2908 "alloc-id": allocID,
2909 "intf-id": intfID,
2910 "onu-id": onuID,
2911 "uni-id": uniID,
2912 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302913 // Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002914 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002915 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002916 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 +05302917 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002918 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002919 }
mgouda86543582025-10-29 20:58:16 +05302920 case IgmpProto:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002921 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302922 log.Fields{
2923 "intf-id": intfID,
2924 "onu-id": onuID,
2925 "uni-id": uniID,
2926 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002927 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002928 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002929 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 +05302930 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002931 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002932 }
mgouda86543582025-10-29 20:58:16 +05302933 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002934 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002935 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002936 }
2937 } else if ethType, ok := classifierInfo[EthType]; ok {
mgouda86543582025-10-29 20:58:16 +05302938 switch ethType.(uint32) {
2939 case EapEthType:
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002940 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002941 "intf-id": intfID,
2942 "onu-id": onuID,
2943 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002944 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002945 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002946 var vlanID uint32
2947 if val, ok := classifierInfo[VlanVid]; ok {
2948 vlanID = (val.(uint32)) & VlanvIDMask
2949 } else {
2950 vlanID = DefaultMgmtVlan
2951 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002952 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); 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 PPPoEDEthType:
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002959 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2960 "tp-id": tpID,
2961 "alloc-id": allocID,
2962 "intf-id": intfID,
2963 "onu-id": onuID,
2964 "uni-id": uniID,
2965 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302966 // Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002967 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002968 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002969 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 +05302970 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002971 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002972 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002973 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002974 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002975 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002976 "intf-id": intfID,
2977 "onu-id": onuID,
2978 "uni-id": uniID,
2979 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302980 // Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002981 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002982 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002983 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 +05302984 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002985 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002986 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002987 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002988 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002989 "intf-id": intfID,
2990 "onu-id": onuID,
2991 "uni-id": uniID,
2992 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302993 // Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002994 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002995 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002996 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 +05302997 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002998 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002999 }
3000 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003001 return olterrors.NewErrInvalidValue(log.Fields{
3002 "intf-id": intfID,
3003 "onu-id": onuID,
3004 "uni-id": uniID,
3005 "classifier": classifierInfo,
3006 "action": actionInfo,
3007 "flow": flow},
3008 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003009 }
3010 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04003011 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003012 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003013 logger.Warn(ctx, err)
3014 }
3015 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003016 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00003017}
3018
Gamze Abakacb0e6772021-06-10 08:32:12 +00003019func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003020 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
3021 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
3022 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 +05303023 for i := 0; i < len(tpInstances); i++ {
3024 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00003025 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003026 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Girish Gowdraf3728b12022-02-02 21:46:51 -08003027 logger.Debugw(ctx, "alloc-is-in-use-on-another-uni",
Gamze Abakacb0e6772021-06-10 08:32:12 +00003028 log.Fields{
3029 "device-id": f.deviceHandler.device.Id,
3030 "intfID": sq.intfID,
3031 "onuID": sq.onuID,
3032 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003033 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00003034 })
3035 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303036 }
3037 }
3038 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003039 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003040}
3041
Neha Sharma96b7bf22020-06-15 10:37:32 +00003042func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003043 for _, field := range flows.GetOfbFields(flow) {
mgouda86543582025-10-29 20:58:16 +05303044 switch field.Type {
3045 case flows.ETH_TYPE:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003046 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003047 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303048 case flows.ETH_DST:
Esin Karamanccb714b2019-11-29 15:02:06 +00003049 classifierInfo[EthDst] = field.GetEthDst()
Girish Gowdraffa52e52022-02-16 15:48:10 -08003050 logger.Debug(ctx, "field-type-eth-dst", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
mgouda86543582025-10-29 20:58:16 +05303051 case flows.ETH_SRC:
Girish Gowdraffa52e52022-02-16 15:48:10 -08003052 classifierInfo[EthSrc] = field.GetEthSrc()
3053 logger.Debug(ctx, "field-type-eth-src", log.Fields{"classifierInfo[ETH_SRC]": classifierInfo[EthSrc].([]uint8)})
mgouda86543582025-10-29 20:58:16 +05303054 case flows.IP_PROTO:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003055 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003056 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303057 case flows.IN_PORT:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003058 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003059 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303060 case flows.VLAN_VID:
Andrea Campanellafaa42152021-10-28 11:50:56 +05303061 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3062 if field.GetVlanVid() != ReservedVlan {
3063 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3064 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3065 }
mgouda86543582025-10-29 20:58:16 +05303066 case flows.VLAN_PCP:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003067 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003068 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303069 case flows.UDP_DST:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003070 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003071 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303072 case flows.UDP_SRC:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003073 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003074 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303075 case flows.IPV4_DST:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003076 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003077 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303078 case flows.IPV4_SRC:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003079 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003080 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303081 case flows.METADATA:
David K. Bainbridge82efc492019-09-04 09:57:11 -07003082 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003083 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
mgouda86543582025-10-29 20:58:16 +05303084 case flows.TUNNEL_ID:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003085 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003086 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
mgouda86543582025-10-29 20:58:16 +05303087 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003088 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003089 return
3090 }
3091 }
3092}
3093
Neha Sharma96b7bf22020-06-15 10:37:32 +00003094func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003095 for _, action := range flows.GetActions(flow) {
mgouda86543582025-10-29 20:58:16 +05303096 switch action.Type {
3097 case flows.OUTPUT:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003098 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003099 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003100 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003101 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003102 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003103 }
mgouda86543582025-10-29 20:58:16 +05303104 case flows.POP_VLAN:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003105 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003106 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303107 case flows.PUSH_VLAN:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003108 if out := action.GetPush(); out != nil {
3109 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003110 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003111 } else {
3112 actionInfo[PushVlan] = true
3113 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003114 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303115 log.Fields{
3116 "push-tpid": actionInfo[TPID].(uint32),
3117 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003118 }
3119 }
mgouda86543582025-10-29 20:58:16 +05303120 case flows.SET_FIELD:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003121 if out := action.GetSetField(); out != nil {
3122 if field := out.GetField(); field != nil {
3123 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003124 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003125 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003126 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3127 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003128 }
3129 }
mgouda86543582025-10-29 20:58:16 +05303130 case flows.GROUP:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003131 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
mgouda86543582025-10-29 20:58:16 +05303132 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00003133 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003134 }
3135 }
3136 return nil
3137}
3138
Neha Sharma96b7bf22020-06-15 10:37:32 +00003139func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003140 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003141 fieldtype := ofbField.GetType()
mgouda86543582025-10-29 20:58:16 +05303142 switch fieldtype {
3143 case ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
Esin Karamanccb714b2019-11-29 15:02:06 +00003144 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3145 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003146 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003147 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003148 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003149 }
mgouda86543582025-10-29 20:58:16 +05303150 case ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
Gamze Abakac43a66e2020-05-11 11:00:42 +00003151 pcp := ofbField.GetVlanPcp()
3152 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003153 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303154 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003155 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003156 }
3157 }
3158}
3159
Neha Sharma96b7bf22020-06-15 10:37:32 +00003160func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003161 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003162 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003163 } else {
3164 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003165 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003166 }
3167}
3168
Neha Sharma96b7bf22020-06-15 10:37:32 +00003169func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003170 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003171 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003172 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003173 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003174 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003175 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003176 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303177 log.Fields{
3178 "newinport": classifierInfo[InPort].(uint32),
3179 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003180 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303181 return olterrors.NewErrNotFound("child-in-port",
3182 log.Fields{
3183 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3184 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003185 }
3186 }
3187 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003188 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003189 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003190 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003191 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003192 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003193 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303194 log.Fields{
3195 "newoutport": actionInfo[Output].(uint32),
3196 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003197 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303198 return olterrors.NewErrNotFound("out-port",
3199 log.Fields{
3200 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3201 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003202 }
3203 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003204 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003205 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003206 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003207 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303208 log.Fields{
3209 "newinport": actionInfo[Output].(uint32),
3210 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003211 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303212 return olterrors.NewErrNotFound("nni-port",
3213 log.Fields{
3214 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3215 "in-port": classifierInfo[InPort].(uint32),
3216 "out-port": actionInfo[Output].(uint32),
3217 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003218 }
3219 }
3220 }
3221 return nil
3222}
Gamze Abakafee36392019-10-03 11:17:24 +00003223
Neha Sharma96b7bf22020-06-15 10:37:32 +00003224func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003225 /* Metadata 8 bytes:
3226 Most Significant 2 Bytes = Inner VLAN
3227 Next 2 Bytes = Tech Profile ID(TPID)
3228 Least Significant 4 Bytes = Port ID
3229 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3230 subscriber related flows.
3231 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003232 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003233 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003234 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003235 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003236 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003237 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003238}
3239
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003240func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003241 for _, sliceElement := range slice {
3242 if sliceElement == item {
3243 return slice
3244 }
3245 }
3246 return append(slice, item)
3247}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303248
yasin saplie87d4bd2021-12-06 09:04:03 +00003249func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3250 for _, sliceElement := range slice {
3251 if sliceElement == item {
3252 return slice
3253 }
3254 }
3255 return append(slice, item)
3256}
3257
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303258// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003259func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003260 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
mgouda86543582025-10-29 20:58:16 +05303261 switch portType {
3262 case voltha.Port_PON_OLT:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003263 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003264 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003265 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003266 log.Fields{
3267 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003268 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003269 return uint32(0), err
3270 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003271 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303272 return intfID, nil
mgouda86543582025-10-29 20:58:16 +05303273 case voltha.Port_ETHERNET_NNI:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003274 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003275 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003276 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003277 log.Fields{
3278 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003279 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003280 return uint32(0), err
3281 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003282 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303283 return intfID, nil
mgouda86543582025-10-29 20:58:16 +05303284 case voltha.Port_ETHERNET_UNI:
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05303285 if _, ok := action[Output]; ok {
3286 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
3287 if err != nil {
3288 logger.Debugw(ctx, "invalid-action-port-number",
3289 log.Fields{
3290 "port-number": action[Output].(uint32),
3291 "err": err})
3292 return uint32(0), nil
3293 }
3294 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
3295 return intfID, nil
3296 } else {
3297 logger.Debugw(ctx, "action-port-number-empty",
3298 log.Fields{
3299 "action": action})
3300 return uint32(0), nil
3301 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303302 }
3303 return uint32(0), nil
3304}
3305
3306// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003307func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3308 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3309 if err != nil {
3310 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3311 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3312 return
3313 }
3314 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003315
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003316 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003317 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003318 f.packetInGemPortLock.RUnlock()
3319
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303320 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003321 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003322 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 +05303323 log.Fields{
3324 "pktinkey": pktInkey,
3325 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003326 return
3327 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303328 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003329 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003330 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003331 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003332
npujarec5762e2020-01-01 14:08:48 +05303333 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003334 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 +05303335 log.Fields{
3336 "pktinkey": pktInkey,
3337 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303338}
3339
Joey Armstrong3f0e2422023-07-05 18:25:41 -04003340// getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003341func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
mgouda86543582025-10-29 20:58:16 +05303342 if len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003343 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003344 return 0, 0, errors.New("invalid packet length")
3345 }
3346 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3347 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3348
3349 var index int8
3350 if outerEthType == 0x8100 {
3351 if innerEthType == 0x8100 {
3352 // q-in-q 802.1ad or 802.1q double tagged packet.
3353 // get the inner vlanId
3354 index = 18
3355 } else {
3356 index = 14
3357 }
3358 priority := (packet[index] >> 5) & 0x7
Akash Kankanala041a2122024-10-16 15:49:22 +05303359 // 13 bits composes vlanId value
Esin Karaman7fb80c22020-07-16 14:23:33 +00003360 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3361 return vlan, priority, nil
3362 }
3363 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3364 return 0, 0, nil
3365}
3366
Joey Armstrong3f0e2422023-07-05 18:25:41 -04003367// clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
Girish Gowdra9602eb42020-09-09 15:50:39 -07003368// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003369func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003370 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003371 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3372 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003373 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003374 "flow-id": flow.Id,
3375 "device-id": f.deviceHandler.device.Id})
3376 // Remove from device
3377 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3378 // DKB
3379 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3380 log.Fields{
3381 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003382 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003383 return err
3384 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003385
3386 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003387}
3388
khenaidoodc2116e2021-10-19 17:33:19 -04003389func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003390 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003391 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003392 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003393 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003394 }
3395
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003396 switch tpInst := tpInst.(type) {
3397 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003398 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003399 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003400 DeviceId: onuDeviceID,
3401 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003402 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003403 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003404 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003405 case *tp_pb.EponTechProfileInstance:
3406 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003407 DeviceId: onuDeviceID,
3408 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003409 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003410 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003411 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003412 default:
3413 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003414 }
khenaidoodc2116e2021-10-19 17:33:19 -04003415 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003416 DeviceId: onuDeviceID,
3417 UniId: uniID,
3418 TpInstancePath: tpPath,
3419 TechTpInstance: nil,
3420 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003421}
3422
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003423// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3424func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003425 intfID := sq.intfID
3426 onuID := sq.onuID
3427 uniID := sq.uniID
3428 tpID := sq.tpID
3429
3430 var reverseDirection string
3431 if sq.direction == tp_pb.Direction_UPSTREAM {
3432 reverseDirection = "downstream"
3433 } else {
3434 reverseDirection = "upstream"
3435 }
3436
3437 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
yasin saplibddc2d72022-02-08 13:10:17 +00003438 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, onuID, uniID, tpID); KvStoreMeter != nil {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003439 return
3440 }
3441
3442 // revert-delete tech-profile instance and delete tech profile id for onu
3443 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})
3444 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3445 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
yasin saplibddc2d72022-02-08 13:10:17 +00003446 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, onuID, uniID, tpID)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003447
3448 // free gem/alloc
3449 switch techprofileInst := sq.tpInst.(type) {
3450 case *tp_pb.TechProfileInstance:
3451 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
yasin saplibddc2d72022-02-08 13:10:17 +00003452 f.resourceMgr.FreeGemPortID(ctx, onuID, uniID, gem.GemportId)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003453 }
yasin saplibddc2d72022-02-08 13:10:17 +00003454 f.resourceMgr.FreeAllocID(ctx, onuID, uniID, techprofileInst.UsScheduler.AllocId, true)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003455 }
3456}
3457
3458// revertSchduler is called when CreateQueues request fails
3459func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3460 // revert scheduler
3461 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})
3462 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
3463 IntfId: sq.intfID, OnuId: sq.onuID,
3464 UniId: sq.uniID, PortNo: sq.uniPort,
3465 TrafficScheds: TrafficSched})
3466}
Girish Gowdra6071f382021-12-14 12:52:04 +05303467
3468// validateMeter validates if there is a meter mismatch for the given direction. It also clears the stale meter if the reference count is zero
3469func (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 +00003470 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, onuID, uniID, tpID)
Girish Gowdra6071f382021-12-14 12:52:04 +05303471 if err != nil {
3472 return olterrors.NewErrNotFound("meter",
3473 log.Fields{"intf-id": intfID,
3474 "onu-id": onuID,
3475 "uni-id": uniID,
3476 "device-id": f.deviceHandler.device.Id}, err)
3477 }
3478
3479 if meterInfo != nil {
3480 // If RefCnt become 0 clear the meter information from the DB.
3481 if meterInfo.MeterID != meterID && meterInfo.RefCnt == 0 {
yasin saplibddc2d72022-02-08 13:10:17 +00003482 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, onuID, uniID, tpID); err != nil {
Girish Gowdra6071f382021-12-14 12:52:04 +05303483 return err
3484 }
3485 } else if meterInfo.MeterID != meterID {
3486 logger.Errorw(ctx, "meter-mismatch-for-direction",
3487 log.Fields{"direction": direction,
3488 "kv-store-meter-id": meterInfo.MeterID,
3489 "meter-id-in-flow": meterID,
3490 "device-id": f.deviceHandler.device.Id})
3491 return olterrors.NewErrInvalidValue(log.Fields{
3492 "unsupported": "meter-id",
3493 "kv-store-meter-id": meterInfo.MeterID,
3494 "meter-id-in-flow": meterID,
3495 "device-id": f.deviceHandler.device.Id}, nil)
3496 }
3497 }
3498 return nil
3499}
Girish Gowdraf3728b12022-02-02 21:46:51 -08003500
3501func (f *OpenOltFlowMgr) removeMeterReference(ctx context.Context, direction string, sq schedQueue) error {
3502 /* After we successfully remove the scheduler configuration on the OLT device,
3503 * delete the meter id on the KV store.
3504 */
yasin saplibddc2d72022-02-08 13:10:17 +00003505 err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Girish Gowdraf3728b12022-02-02 21:46:51 -08003506 if err != nil {
3507 return olterrors.NewErrAdapter("unable-to-remove-meter",
3508 log.Fields{
3509 "onu": sq.onuID,
3510 "device-id": f.deviceHandler.device.Id,
3511 "intf-id": sq.intfID,
3512 "onu-id": sq.onuID,
3513 "uni-id": sq.uniID,
3514 "uni-port": sq.uniPort}, err)
3515 }
3516 logger.Debugw(ctx, "removed-meter-from-KV-store-successfully",
3517 log.Fields{
3518 "dir": direction,
3519 "device-id": f.deviceHandler.device.Id,
3520 "intf-id": sq.intfID,
3521 "onu-id": sq.onuID,
3522 "uni-id": sq.uniID,
3523 "uni-port": sq.uniPort})
3524 return err
3525}