blob: 5b4a47491237c15510b1f99fdf792a21f65ba7e7 [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
392 if sq.direction == tp_pb.Direction_UPSTREAM {
393 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
394 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
395 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
396 }
397 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
398 TrafficSched[0].TechProfileId = sq.tpID
399
Manikkaraj kb1d51442019-07-23 10:41:02 -0400400 /* Lets make a simple assumption that if the meter-id is present on the KV store,
401 * then the scheduler and queues configuration is applied on the OLT device
402 * in the given direction.
403 */
yasin saplibddc2d72022-02-08 13:10:17 +0000404 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400405 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530406 return olterrors.NewErrNotFound("meter",
407 log.Fields{"intf-id": sq.intfID,
408 "onu-id": sq.onuID,
409 "uni-id": sq.uniID,
410 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400411 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000412
Girish Gowdraf3728b12022-02-02 21:46:51 -0800413 // update reference count and return if the meter was already installed before
Girish Gowdra6071f382021-12-14 12:52:04 +0530414 if meterInfo != nil && meterInfo.MeterID == sq.meterID {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800415 logger.Infow(ctx, "scheduler-already-created-for-direction",
Girish Gowdra6071f382021-12-14 12:52:04 +0530416 log.Fields{"device-id": f.deviceHandler.device.Id, "direction": direction, "meter-id": sq.meterID})
yasin saplibddc2d72022-02-08 13:10:17 +0000417 if err = f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, direction, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800418 return err
419 }
420
421 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); allocExists {
422 // Alloc object was already created as part of flow setup on another uni of the onu for the same service.
423 // Just create gem ports and traffic queues on the current uni for the given service
424 logger.Infow(ctx, "alloc in use on another uni, schedulers already created, creating queues only",
425 log.Fields{"intf-id": sq.intfID,
426 "onu-id": sq.onuID,
427 "uni-id": sq.uniID,
428 "tp-id": sq.tpID,
429 "device-id": f.deviceHandler.device.Id})
430 // The upstream scheduler is already created. We only need to create the queues
431 // If there are multiple upstream flows on a given uni, then it is possible that
432 // we call pushTrafficQueues multiple times, but that is OK as BAL returns OK.
433 // TODO: Find better mechanism to not duplicate request.
434 if err = f.pushTrafficQueues(ctx, sq, TrafficSched); err != nil {
435 return olterrors.NewErrAdapter("failure-pushing-traffic-queues-to-device",
436 log.Fields{"intf-id": sq.intfID,
437 "direction": sq.direction,
438 "device-id": f.deviceHandler.device.Id}, err)
439 }
440 } else {
441 logger.Infow(ctx, "alloc not in use on another uni, only meter ref cnt updated",
442 log.Fields{"intf-id": sq.intfID,
443 "onu-id": sq.onuID,
444 "uni-id": sq.uniID,
445 "tp-id": sq.tpID,
446 "device-id": f.deviceHandler.device.Id})
447 }
448 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400449 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000450
Neha Sharma96b7bf22020-06-15 10:37:32 +0000451 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530452 log.Fields{
453 "meter-id": sq.meterID,
Girish Gowdra6071f382021-12-14 12:52:04 +0530454 "direction": direction,
Shrey Baid26912972020-04-16 21:02:31 +0530455 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000456
Girish Gowdraa482f272021-03-24 23:04:19 -0700457 found := false
458 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000459 if sq.flowMetadata != nil {
460 for _, meter := range sq.flowMetadata.Meters {
461 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700462 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700463 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 +0000464 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700465 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530466 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700467 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400468 break
469 }
470 }
471 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000472 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400473 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700474 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530475 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800476 "reason": "Could-not-get-meterbands-from-flowMetadata",
477 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530478 "meter-id": sq.meterID,
479 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400480 }
Gamze Abaka01174422021-03-10 06:55:27 +0000481
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700482 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530483 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
484 log.Fields{"intf-id": sq.intfID,
485 "direction": sq.direction,
486 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400487 }
488
salmansiddiqui7ac62132019-08-22 03:58:50 +0000489 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400490 * store the meter id on the KV store, for further reference.
491 */
yasin saplibddc2d72022-02-08 13:10:17 +0000492 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530493 return olterrors.NewErrAdapter("failed-updating-meter-id",
494 log.Fields{"onu-id": sq.onuID,
495 "meter-id": sq.meterID,
496 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400497 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000498 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Girish Gowdra6071f382021-12-14 12:52:04 +0530499 log.Fields{"direction": direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700500 "meter-info": meterInfo,
501 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400502 return nil
503}
504
Girish Gowdraf3728b12022-02-02 21:46:51 -0800505func (f *OpenOltFlowMgr) pushTrafficQueues(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
506 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
507 if err != nil {
508 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
509 log.Fields{"intf-id": sq.intfID,
510 "direction": sq.direction,
511 "device-id": f.deviceHandler.device.Id}, err)
512 }
513 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
514 log.Fields{"direction": sq.direction,
515 "traffic-queues": trafficQueues,
516 "device-id": f.deviceHandler.device.Id})
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530517 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, NetworkIntfId: sq.nniIntfID, OnuId: sq.onuID,
Girish Gowdraf3728b12022-02-02 21:46:51 -0800518 UniId: sq.uniID, PortNo: sq.uniPort,
519 TrafficQueues: trafficQueues,
520 TechProfileId: TrafficSched[0].TechProfileId}
Akash Kankanala041a2122024-10-16 15:49:22 +0530521 if _, err = f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800522 if len(queues.TrafficQueues) > 1 {
523 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
524 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
525 }
526 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
527 }
528 return err
529}
530
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700531func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700532 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000533
534 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530535 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
536 log.Fields{"intf-id": sq.intfID,
537 "direction": sq.direction,
538 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000539 }
540
Gamze Abakacb0e6772021-06-10 08:32:12 +0000541 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
542 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
543 log.Fields{
544 "direction": sq.direction,
545 "TrafficScheds": TrafficSched,
546 "device-id": f.deviceHandler.device.Id,
547 "intfID": sq.intfID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530548 "nniIntfID": sq.nniIntfID,
Gamze Abakacb0e6772021-06-10 08:32:12 +0000549 "onuID": sq.onuID,
550 "uniID": sq.uniID})
551 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
552 IntfId: sq.intfID, OnuId: sq.onuID,
553 UniId: sq.uniID, PortNo: sq.uniPort,
554 TrafficScheds: TrafficSched}); err != nil {
555 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
556 }
557 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
558 "direction": sq.direction,
559 "traffic-queues": trafficQueues,
560 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000561 }
562
563 // On receiving the CreateTrafficQueues request, the driver should create corresponding
564 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000565 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530566 log.Fields{"direction": sq.direction,
567 "traffic-queues": trafficQueues,
568 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000569 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530570 NetworkIntfId: sq.nniIntfID,
571 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000572 TrafficQueues: trafficQueues,
573 TechProfileId: TrafficSched[0].TechProfileId}
574 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
575 if len(queues.TrafficQueues) > 1 {
576 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
577 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
578 }
579 f.revertScheduler(ctx, sq, TrafficSched)
Shrey Baid26912972020-04-16 21:02:31 +0530580 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000581 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000582 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530583 "direction": sq.direction,
584 "traffic-queues": trafficQueues,
585 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000586
Esin Karamanccb714b2019-11-29 15:02:06 +0000587 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700588 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000589 if len(multicastTrafficQueues) > 0 {
Akash Kankanala041a2122024-10-16 15:49:22 +0530590 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present { // assumed that there is only one queue per PON for the multicast service
591 // the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
592 // just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000593 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000594 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700595 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000596 gemPortID: multicastQueuePerPonPort.GemportId,
597 servicePriority: multicastQueuePerPonPort.Priority,
598 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700599 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Akash Kankanala041a2122024-10-16 15:49:22 +0530600 // also store the queue info in kv store
yasin saplibddc2d72022-02-08 13:10:17 +0000601 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700602 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400603 return err
604 }
Shrey Baid26912972020-04-16 21:02:31 +0530605
Neha Sharma96b7bf22020-06-15 10:37:32 +0000606 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000607 }
608 }
609 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000610 return nil
611}
612
Girish Gowdraf3728b12022-02-02 21:46:51 -0800613// RemoveQueues removes the traffic queues from the device based on the given schedQueue info
614func (f *OpenOltFlowMgr) RemoveQueues(ctx context.Context, sq schedQueue) error {
615 var err error
616 logger.Infow(ctx, "removing-queue-in-olt",
617 log.Fields{
618 "direction": sq.direction,
619 "intf-id": sq.intfID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530620 "nniIntfID": sq.nniIntfID,
Girish Gowdraf3728b12022-02-02 21:46:51 -0800621 "onu-id": sq.onuID,
622 "uni-id": sq.uniID,
623 "uni-port": sq.uniPort,
624 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400625
Girish Gowdraf3728b12022-02-02 21:46:51 -0800626 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
627 if err != nil {
628 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
629 log.Fields{
630 "intf-id": sq.intfID,
631 "direction": sq.direction,
632 "device-id": f.deviceHandler.device.Id}, err)
633 }
634
635 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
636 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530637 NetworkIntfId: sq.nniIntfID,
638 UniId: sq.uniID, PortNo: sq.uniPort,
Girish Gowdraf3728b12022-02-02 21:46:51 -0800639 TrafficQueues: TrafficQueues,
640 TechProfileId: sq.tpID}); err != nil {
641 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
642 log.Fields{
643 "intf-id": sq.intfID,
644 "traffic-queues": TrafficQueues,
645 "device-id": f.deviceHandler.device.Id}, err)
646 }
647 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
648
649 return err
650}
651
652// RemoveScheduler removes the traffic scheduler from the device based on the given schedQueue info
653func (f *OpenOltFlowMgr) RemoveScheduler(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400654 var Direction string
655 var SchedCfg *tp_pb.SchedulerConfig
656 var err error
Girish Gowdraf3728b12022-02-02 21:46:51 -0800657 logger.Infow(ctx, "removing-scheduler-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530658 log.Fields{
659 "direction": sq.direction,
660 "intf-id": sq.intfID,
661 "onu-id": sq.onuID,
662 "uni-id": sq.uniID,
663 "uni-port": sq.uniPort,
664 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000665 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700666 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400667 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000668 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700669 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400670 Direction = "downstream"
671 }
672
Girish Gowdraa482f272021-03-24 23:04:19 -0700673 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 -0400674
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700675 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000676 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000677
Girish Gowdraf3728b12022-02-02 21:46:51 -0800678 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
679 IntfId: sq.intfID, OnuId: sq.onuID,
680 UniId: sq.uniID, PortNo: sq.uniPort,
681 TrafficScheds: TrafficSched}); err != nil {
682 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530683 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800684 "intf-id": sq.intfID,
685 "traffic-schedulers": TrafficSched,
686 "onu-id": sq.onuID,
687 "uni-id": sq.uniID,
688 "uni-port": sq.uniPort}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000689 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400690
Girish Gowdraf3728b12022-02-02 21:46:51 -0800691 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
692 log.Fields{"device-id": f.deviceHandler.device.Id,
693 "intf-id": sq.intfID,
694 "onu-id": sq.onuID,
695 "uni-id": sq.uniID,
696 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400697
Girish Gowdraf3728b12022-02-02 21:46:51 -0800698 if sq.direction == tp_pb.Direction_UPSTREAM {
699 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
700 // Delete the TCONT on the ONU.
701 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
yasin saplibddc2d72022-02-08 13:10:17 +0000702 tpPath := f.getTPpath(ctx, uni, sq.tpID)
Akash Kankanala041a2122024-10-16 15:49:22 +0530703 if err = f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800704 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Gamze Abakacb0e6772021-06-10 08:32:12 +0000705 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800706 "intf": sq.intfID,
707 "onu-id": sq.onuID,
708 "uni-id": sq.uniID,
709 "device-id": f.deviceHandler.device.Id,
710 "alloc-id": allocID})
Gamze Abakacb0e6772021-06-10 08:32:12 +0000711 }
712 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000713
714 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400715 * delete the meter id on the KV store.
716 */
Girish Gowdraf3728b12022-02-02 21:46:51 -0800717 err = f.removeMeterReference(ctx, Direction, sq)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400718 return err
719}
720
Girish Gowdra197acc12021-08-16 10:59:45 -0700721// We are trying to force remove the schedulers and queues here if one exists for the given key.
722// We ignore any errors encountered in the process. The errors most likely are encountered when
723// the schedulers and queues are already cleared for the given key.
724func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
Girish Gowdra197acc12021-08-16 10:59:45 -0700725 var schedCfg *tp_pb.SchedulerConfig
Girish Gowdra197acc12021-08-16 10:59:45 -0700726 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
727 log.Fields{
728 "direction": sq.direction,
729 "intf-id": sq.intfID,
730 "onu-id": sq.onuID,
731 "uni-id": sq.uniID,
732 "uni-port": sq.uniPort,
733 "tp-id": sq.tpID,
734 "device-id": f.deviceHandler.device.Id})
735 if sq.direction == tp_pb.Direction_UPSTREAM {
736 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
737 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
738 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
739 }
740
741 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
742 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
743 TrafficSched[0].TechProfileId = sq.tpID
744
745 // Remove traffic queues. Ignore any errors, just log them.
746 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
747 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
748 "direction": sq.direction,
749 "intf-id": sq.intfID,
750 "onu-id": sq.onuID,
751 "uni-id": sq.uniID,
752 "uni-port": sq.uniPort,
753 "tp-id": sq.tpID,
754 "device-id": f.deviceHandler.device.Id,
755 "err": err})
756 } else {
757 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
758 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
759 UniId: sq.uniID, PortNo: sq.uniPort,
760 TrafficQueues: TrafficQueues,
761 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
762 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
763 "direction": sq.direction,
764 "intf-id": sq.intfID,
765 "onu-id": sq.onuID,
766 "uni-id": sq.uniID,
767 "uni-port": sq.uniPort,
768 "tp-id": sq.tpID,
769 "device-id": f.deviceHandler.device.Id,
770 "err": err})
Girish Gowdra197acc12021-08-16 10:59:45 -0700771 } else {
772 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
773 "direction": sq.direction,
774 "intf-id": sq.intfID,
775 "onu-id": sq.onuID,
776 "uni-id": sq.uniID,
777 "uni-port": sq.uniPort,
778 "tp-id": sq.tpID})
779 }
780 }
781
782 // Remove traffic schedulers. Ignore any errors, just log them.
Akash Kankanala041a2122024-10-16 15:49:22 +0530783 if _, err := f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Gowdra197acc12021-08-16 10:59:45 -0700784 IntfId: sq.intfID, OnuId: sq.onuID,
785 UniId: sq.uniID, PortNo: sq.uniPort,
786 TrafficScheds: TrafficSched}); err != nil {
787 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
788 "direction": sq.direction,
789 "intf-id": sq.intfID,
790 "onu-id": sq.onuID,
791 "uni-id": sq.uniID,
792 "uni-port": sq.uniPort,
793 "tp-id": sq.tpID,
794 "device-id": f.deviceHandler.device.Id,
795 "err": err})
796 } else {
797 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
798 "direction": sq.direction,
799 "intf-id": sq.intfID,
800 "onu-id": sq.onuID,
801 "uni-id": sq.uniID,
802 "uni-port": sq.uniPort,
803 "tp-id": sq.tpID})
804 }
805}
806
Gamze Abakafee36392019-10-03 11:17:24 +0000807// This function allocates tconts and GEM ports for an ONU
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530808func (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 +0000809 var allocIDs []uint32
810 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530811 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530812 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000813 var err error
yasin saplibddc2d72022-02-08 13:10:17 +0000814 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, onuID, uniID)
815 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, onuID, uniID)
816 tpPath := f.getTPpath(ctx, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530817
Neha Sharma96b7bf22020-06-15 10:37:32 +0000818 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530819 "intf-id": intfID,
820 "onu-id": onuID,
821 "uni-id": uniID,
822 "device-id": f.deviceHandler.device.Id,
823 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530824
Manikkaraj kb1d51442019-07-23 10:41:02 -0400825 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700826 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000827 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000828 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530829 log.Fields{
830 "path": tpPath,
831 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700832 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000833 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530834 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000835 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530836 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700837 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530838 "tp-id": TpID,
839 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000840 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530841 }
yasin saplibddc2d72022-02-08 13:10:17 +0000842 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700843 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400844 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530845 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000846 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530847 log.Fields{
848 "uni": uni,
849 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530850 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530851 }
Gamze Abakafee36392019-10-03 11:17:24 +0000852
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700853 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700854 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700855 if UsMeterID != 0 {
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530856 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, nniIntfID: nniIntfID, onuID: onuID, uniID: uniID, tpID: TpID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700857 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
858 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000859 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700860 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700861 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700862 "onu-id": onuID,
863 "uni-id": uniID,
864 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700865 "meter-id": UsMeterID,
866 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000867 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700868 return 0, nil, nil
869 }
870 }
871 if DsMeterID != 0 {
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530872 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, nniIntfID: nniIntfID, onuID: onuID, uniID: uniID, tpID: TpID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700873 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
874 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000875 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700876 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700877 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700878 "onu-id": onuID,
879 "uni-id": uniID,
880 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700881 "meter-id": DsMeterID,
882 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000883 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700884 return 0, nil, nil
885 }
886 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700887 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700888 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700889 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700890 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700891 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000892
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700893 if tpInstanceExists {
894 return allocID, gemPortIDs, techProfileInstance
895 }
896
897 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700898 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700899 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000900 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700901 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700902 "intf-id": intfID,
903 "onu-id": onuID,
904 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700905 "alloc-ids": allocIDs,
906 "gemports": allgemPortIDs,
907 "device-id": f.deviceHandler.device.Id})
908 // Send Tconts and GEM ports to KV store
909 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530910 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400911 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700912 // CreateSchedulerQueues for EPON needs to be implemented here
913 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700914 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700915 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700916 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700917 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700918 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700919
920 if tpInstanceExists {
921 return allocID, gemPortIDs, techProfileInstance
922 }
923
924 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700925 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700926 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000927 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700928 log.Fields{
929 "alloc-ids": allocIDs,
930 "gemports": allgemPortIDs,
931 "device-id": f.deviceHandler.device.Id})
932 // Send Tconts and GEM ports to KV store
933 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
934 return allocID, gemPortIDs, techProfileInstance
935 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000936 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700937 log.Fields{
938 "tpInst": tpInst})
939 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530940 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530941}
942
npujarec5762e2020-01-01 14:08:48 +0530943func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000944 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530945 log.Fields{
946 "intf-id": intfID,
947 "onu-id": onuID,
948 "uni-id": uniID,
949 "alloc-id": allocID,
950 "gemport-ids": gemPortIDs,
951 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530952 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
yasin saplibddc2d72022-02-08 13:10:17 +0000953 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, onuID, uniID, allocID); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000954 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 +0530955 }
yasin saplibddc2d72022-02-08 13:10:17 +0000956 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, onuID, uniID, gemPortIDs); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000957 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 +0530958 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700959
Neha Sharma96b7bf22020-06-15 10:37:32 +0000960 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 -0400961 for _, gemPort := range gemPortIDs {
yasin saplibddc2d72022-02-08 13:10:17 +0000962 if err := f.resourceMgr.AddGemToOnuGemInfo(ctx, onuID, gemPort); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000963 logger.Errorw(ctx, "error-while-uploading-onugeminfos-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "gemPort": gemPort})
964 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400965 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530966}
967
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700968func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530969 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000970 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700971 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
972 var err error
pnalmas937a24d2025-01-16 18:48:30 +0530973 f.techprofile, err = tp.NewTechProfile(ctx, intfID, f.resourceMgr.DeviceID, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700974 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
975 if err != nil || f.techprofile == nil {
976 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
977 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
978 }
979 logger.Debugw(ctx, "init-tech-profile-done",
980 log.Fields{
981 "intf-id": intfID,
982 "device-id": f.deviceHandler.device.Id})
983 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700984 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530985 }
986 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700987 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
988 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 +0530989}
990
Gamze Abaka7650be62021-02-26 10:50:36 +0000991func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Girish Gowdraffa52e52022-02-16 15:48:10 -0800992 flowContext.classifier[PacketTagType] = SingleTag
993 // extract the cvid/inner-vid from the write metadata
994 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
995 if writeMetadata != 0 {
996 // Writemetadata field is 8 bytes
997 // cvid is on the outer most two bytes of the write metadata
998 cvid := (writeMetadata & 0xffff000000000000) >> 48
999 // if the cvid does not match the classifier vlan, then this indicates it is a double tagged packet
1000 if cvid != flowContext.classifier[VlanVid] && cvid != 0 {
1001 flowContext.classifier[PacketTagType] = DoubleTag
1002 }
1003 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001004 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301005 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001006 "uplinkClassifier": flowContext.classifier,
1007 "uplinkAction": flowContext.action})
1008 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301009}
1010
Gamze Abaka7650be62021-02-26 10:50:36 +00001011func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
1012 downlinkClassifier := flowContext.classifier
1013 downlinkAction := flowContext.action
Girish Gowdraffa52e52022-02-16 15:48:10 -08001014 // default to single tag. If we detect an inner cvid from write-metadata, then we mark the PacketTagType as DoubleTag
1015 downlinkClassifier[PacketTagType] = SingleTag
1016 // extract the cvid/inner-vid from the write metadata
1017 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
1018 if writeMetadata != 0 {
1019 // Writemetadata field is 8 bytes
1020 // cvid is on the outer most two bytes of the write metadata
1021 if cvid := (writeMetadata & 0xffff000000000000) >> 48; cvid != 0 {
1022 downlinkClassifier[PacketTagType] = DoubleTag
1023 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301024 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001025 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301026 log.Fields{
1027 "downlinkClassifier": downlinkClassifier,
1028 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001029
Girish Gowdraffa52e52022-02-16 15:48:10 -08001030 // If Pop Vlan action is specified, set the vlan to be popped from the classifier vlan match field.
1031 // The matched vlan is the one that is getting popped.
1032 if val, ok := downlinkAction[PopVlan]; ok && val.(bool) {
1033 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1034 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
1035 if ok {
1036 downlinkAction[VlanVid] = dlClVid & 0xfff
1037 }
Girish Gowdra26f344b2019-10-23 14:39:13 +05301038 }
1039
Gamze Abaka7650be62021-02-26 10:50:36 +00001040 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301041}
1042
Gamze Abaka7650be62021-02-26 10:50:36 +00001043func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001044 intfID := flowContext.intfID
1045 onuID := flowContext.onuID
1046 uniID := flowContext.uniID
1047 classifier := flowContext.classifier
1048 action := flowContext.action
1049 allocID := flowContext.allocID
1050 gemPortID := flowContext.gemPortID
1051 tpID := flowContext.tpID
1052 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001053 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301054 log.Fields{
1055 "intf-id": intfID,
1056 "onu-id": onuID,
1057 "uni-id": uniID,
1058 "device-id": f.deviceHandler.device.Id,
1059 "classifier": classifier,
1060 "action": action,
1061 "direction": direction,
1062 "alloc-id": allocID,
1063 "gemport-id": gemPortID,
1064 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001065
yasin saplibddc2d72022-02-08 13:10:17 +00001066 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001067 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001068 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301069 log.Fields{
1070 "device-id": f.deviceHandler.device.Id,
1071 "intf-id": intfID,
1072 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001073 return nil
yasin saplid0566272021-12-21 09:10:30 +00001074 } else if err != nil {
1075 logger.Errorw(ctx, "aborting-addSymmetricDataPathFlow--flow-may-already-exist",
1076 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1077 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301078 }
yasin saplid0566272021-12-21 09:10:30 +00001079
David K. Bainbridge794735f2020-02-11 21:01:37 -08001080 classifierProto, err := makeOpenOltClassifierField(classifier)
1081 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301082 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301083 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001084 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301085 log.Fields{
1086 "classifier": *classifierProto,
1087 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001088 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001089 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301090 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301091 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001092 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301093 log.Fields{
1094 "action": *actionProto,
1095 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001096 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301097 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301098 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001099 log.Fields{
1100 "classifier": classifier,
1101 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301102 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001103 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301104 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001105
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001106 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001107 OnuId: int32(onuID),
1108 UniId: int32(uniID),
1109 FlowId: logicalFlow.Id,
1110 FlowType: direction,
1111 AllocId: int32(allocID),
1112 NetworkIntfId: int32(networkIntfID),
1113 GemportId: int32(gemPortID),
1114 Classifier: classifierProto,
1115 Action: actionProto,
1116 Priority: int32(logicalFlow.Priority),
1117 Cookie: logicalFlow.Cookie,
1118 PortNo: flowContext.portNo,
1119 TechProfileId: tpID,
1120 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1121 PbitToGemport: flowContext.pbitToGem,
1122 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001123 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001124 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001125 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301126 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001127 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301128 log.Fields{"direction": direction,
1129 "device-id": f.deviceHandler.device.Id,
1130 "flow": flow,
1131 "intf-id": intfID,
1132 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001133
David K. Bainbridge794735f2020-02-11 21:01:37 -08001134 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301135}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001136
Gamze Abaka7650be62021-02-26 10:50:36 +00001137func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001138 intfID := flowContext.intfID
1139 onuID := flowContext.onuID
1140 uniID := flowContext.uniID
1141 logicalFlow := flowContext.logicalFlow
1142 classifier := flowContext.classifier
1143 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301144
Neha Sharma96b7bf22020-06-15 10:37:32 +00001145 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301146 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301147 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001148 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301149 "action": action,
1150 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001151 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301152 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301153
1154 // Clear the action map
1155 for k := range action {
1156 delete(action, k)
1157 }
1158
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001159 action[TrapToHost] = true
1160 classifier[UDPSrc] = uint32(68)
1161 classifier[UDPDst] = uint32(67)
1162 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301163
yasin saplibddc2d72022-02-08 13:10:17 +00001164 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001165 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001166 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301167 log.Fields{
1168 "device-id": f.deviceHandler.device.Id,
1169 "intf-id": intfID,
1170 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001171 return nil
yasin saplid0566272021-12-21 09:10:30 +00001172 } else if err != nil {
1173 logger.Errorw(ctx, "aborting-addDHCPTrapFlow--flow-may-already-exist",
1174 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1175 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301176 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301177
Neha Sharma96b7bf22020-06-15 10:37:32 +00001178 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301179 log.Fields{
1180 "ul_classifier": classifier,
1181 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001182 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301183 "intf-id": intfID,
1184 "onu-id": onuID,
1185 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301186
David K. Bainbridge794735f2020-02-11 21:01:37 -08001187 classifierProto, err := makeOpenOltClassifierField(classifier)
1188 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301189 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301190 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001191 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001192 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001193 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301194 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301195 }
1196
David K. Bainbridge794735f2020-02-11 21:01:37 -08001197 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001198 OnuId: int32(onuID),
1199 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001200 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001201 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001202 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001203 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001204 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301205 Classifier: classifierProto,
1206 Action: actionProto,
1207 Priority: int32(logicalFlow.Priority),
1208 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001209 PortNo: flowContext.portNo,
1210 TechProfileId: flowContext.tpID,
1211 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1212 PbitToGemport: flowContext.pbitToGem,
1213 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001214 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001215 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001216 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001217 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001218 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301219 log.Fields{
1220 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001221 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301222 "intf-id": intfID,
1223 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301224
David K. Bainbridge794735f2020-02-11 21:01:37 -08001225 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301226}
1227
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001228// addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001229func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1230 delete(flowContext.classifier, VlanVid)
1231 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001232}
1233
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001234// addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001235func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001236 intfID := flowContext.intfID
1237 onuID := flowContext.onuID
1238 uniID := flowContext.uniID
1239 logicalFlow := flowContext.logicalFlow
1240 classifier := flowContext.classifier
1241 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001242
Neha Sharma96b7bf22020-06-15 10:37:32 +00001243 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001244 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301245 return olterrors.NewErrNotFound("nni-interface-id",
1246 log.Fields{
1247 "classifier": classifier,
1248 "action": action,
1249 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001250 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001251 }
1252
1253 // Clear the action map
1254 for k := range action {
1255 delete(action, k)
1256 }
1257
1258 action[TrapToHost] = true
1259 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001260
yasin saplibddc2d72022-02-08 13:10:17 +00001261 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001262 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001263 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001264 return nil
yasin saplid0566272021-12-21 09:10:30 +00001265 } else if err != nil {
1266 logger.Errorw(ctx, "aborting-addUpstreamTrapFlow--flow-may-already-exist",
1267 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1268 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00001269 }
1270
Neha Sharma96b7bf22020-06-15 10:37:32 +00001271 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301272 log.Fields{
1273 "ul_classifier": classifier,
1274 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001275 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301276 "device-id": f.deviceHandler.device.Id,
1277 "intf-id": intfID,
1278 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001279
David K. Bainbridge794735f2020-02-11 21:01:37 -08001280 classifierProto, err := makeOpenOltClassifierField(classifier)
1281 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301282 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001283 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001284 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301285 log.Fields{
1286 "classifier": *classifierProto,
1287 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001288 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001289 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301290 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001291 }
1292
David K. Bainbridge794735f2020-02-11 21:01:37 -08001293 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001294 OnuId: int32(onuID),
1295 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001296 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001297 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001298 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001299 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001300 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001301 Classifier: classifierProto,
1302 Action: actionProto,
1303 Priority: int32(logicalFlow.Priority),
1304 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001305 PortNo: flowContext.portNo,
1306 TechProfileId: flowContext.tpID,
1307 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1308 PbitToGemport: flowContext.pbitToGem,
1309 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001310 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001311
David K. Bainbridge794735f2020-02-11 21:01:37 -08001312 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001313 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 -08001314 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001315
David K. Bainbridge794735f2020-02-11 21:01:37 -08001316 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001317}
1318
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001319// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001320func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1321 intfID := flowContext.intfID
1322 onuID := flowContext.onuID
1323 uniID := flowContext.uniID
1324 portNo := flowContext.portNo
1325 allocID := flowContext.allocID
1326 gemPortID := flowContext.gemPortID
1327 logicalFlow := flowContext.logicalFlow
1328 classifier := flowContext.classifier
1329 action := flowContext.action
1330
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001331 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301332 log.Fields{
1333 "intf-id": intfID,
1334 "onu-id": onuID,
1335 "port-no": portNo,
1336 "alloc-id": allocID,
1337 "gemport-id": gemPortID,
1338 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001339 "flow": logicalFlow,
1340 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301341
1342 uplinkClassifier := make(map[string]interface{})
1343 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301344
manikkaraj kbf256be2019-03-25 00:13:48 +05301345 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001346 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001347 uplinkClassifier[PacketTagType] = SingleTag
1348 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001349 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301350 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001351 uplinkAction[TrapToHost] = true
yasin saplibddc2d72022-02-08 13:10:17 +00001352 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001353 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001354 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301355 "device-id": f.deviceHandler.device.Id,
1356 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001357 "intf-id": intfID,
1358 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001359 return nil
yasin saplid0566272021-12-21 09:10:30 +00001360 } else if err != nil {
1361 logger.Errorw(ctx, "aborting-addEthTypeBasedFlow--flow-may-already-exist",
1362 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1363 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301364 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301365 // Add Uplink EthType Flow
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001366 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301367 log.Fields{
1368 "ul_classifier": uplinkClassifier,
1369 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001370 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301371 "device-id": f.deviceHandler.device.Id,
1372 "intf-id": intfID,
1373 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301374
David K. Bainbridge794735f2020-02-11 21:01:37 -08001375 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1376 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301377 return olterrors.NewErrInvalidValue(log.Fields{
1378 "classifier": uplinkClassifier,
1379 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301380 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001381 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301382 log.Fields{
1383 "classifier": *classifierProto,
1384 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001385 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001386 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301387 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301388 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001389 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301390 log.Fields{
1391 "action": *actionProto,
1392 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001393 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301394 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301395 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001396 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301397 "action": action,
1398 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001399 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301400 }
1401
David K. Bainbridge794735f2020-02-11 21:01:37 -08001402 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001403 OnuId: int32(onuID),
1404 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001405 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001406 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001407 AllocId: int32(allocID),
1408 NetworkIntfId: int32(networkIntfID),
1409 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301410 Classifier: classifierProto,
1411 Action: actionProto,
1412 Priority: int32(logicalFlow.Priority),
1413 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001414 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001415 TechProfileId: flowContext.tpID,
1416 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1417 PbitToGemport: flowContext.pbitToGem,
1418 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001419 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001420 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001421 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001422 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001423 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301424 log.Fields{
1425 "device-id": f.deviceHandler.device.Id,
1426 "onu-id": onuID,
1427 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001428 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301429 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001430
David K. Bainbridge794735f2020-02-11 21:01:37 -08001431 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301432}
1433
David K. Bainbridge794735f2020-02-11 21:01:37 -08001434func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001435 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001436
1437 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1438 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1439 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001440 if vlanID != ReservedVlan {
1441 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001442 classifier.OVid = vid
1443 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301444 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07001445 // The classifierInfo[Metadata] is set for the following flows
1446 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
1447 // - Mcast flow that points to a group in the treatment
1448 // This value, when present and valid (not 0 and not 4096), is interpreted as below
1449 // - inner vid for a double tagged packet in the datapath flow
1450 // - outer vid for a single tagged packet in the datapath flow
1451 // - inner vid in the mcast flow that points to a group
David K. Bainbridge82efc492019-09-04 09:57:11 -07001452 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1453 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301454 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1455 // 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 +05301456 // 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 +05301457 // becomes the IVid.
1458 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1459 if vid != ReservedVlan {
1460 classifier.IVid = vid
1461 }
1462 } else {
1463 if vid != ReservedVlan {
1464 classifier.OVid = vid
1465 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001466 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301467 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301468 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001469 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301470 classifier.OPbits = vlanPcp
1471 } else {
1472 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301473 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001474 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1475 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1476 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1477 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001478 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001479 classifier.SrcMac, _ = classifierInfo[EthSrc].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001480 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1481 classifier.PktTagType = pktTagType
1482
1483 switch pktTagType {
1484 case SingleTag:
1485 case DoubleTag:
1486 case Untagged:
1487 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001488 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301489 }
1490 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001491 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301492}
1493
Akash Kankanala041a2122024-10-16 15:49:22 +05301494// nolint: unparam
1495// TODO: Improvise the function & remove the unparam lint, currently it is always returning 'nil' as error.
Gamze Abaka724d0852020-03-18 12:10:24 +00001496func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001497 var actionCmd openoltpb2.ActionCmd
1498 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301499 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001500 if _, ok := actionInfo[PopVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001501 // Pop outer vid
manikkaraj kbf256be2019-03-25 00:13:48 +05301502 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001503 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001504 // Remark inner pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001505 action.Cmd.RemarkInnerPbits = true
1506 action.IPbits = actionInfo[VlanPcp].(uint32)
1507 if _, ok := actionInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001508 // Remark inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001509 action.Cmd.TranslateInnerTag = true
1510 action.IVid = actionInfo[VlanVid].(uint32)
1511 }
1512 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001513 } else if _, ok := actionInfo[PushVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001514 // push outer vid
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001515 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301516 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001517 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001518 // translate outer pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001519 action.OPbits = actionInfo[VlanPcp].(uint32)
1520 action.Cmd.RemarkOuterPbits = true
1521 if _, ok := classifierInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001522 // translate inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001523 action.IVid = classifierInfo[VlanVid].(uint32)
1524 action.Cmd.TranslateInnerTag = true
1525 }
1526 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001527 } else if _, ok := actionInfo[TrapToHost]; ok {
1528 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001529 } else if _, ok := actionInfo[VlanVid]; ok {
1530 // Translate outer vid
1531 action.Cmd.TranslateOuterTag = true
1532 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301533 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301534 // When OLT is transparent to vlans no-action is valid.
1535 /*
1536 else {
1537 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1538 }
1539 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001540 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301541}
1542
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001543// getTPpath return the ETCD path for a given UNI port
yasin saplibddc2d72022-02-08 13:10:17 +00001544func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001545 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301546}
1547
Gamze Abakafee36392019-10-03 11:17:24 +00001548// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001549// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1550// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1551// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1552// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1553// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1554// because it was observed that if the ONU device was deleted too soon after the flows were
1555// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1556// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1557// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001558func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
yasin saplibddc2d72022-02-08 13:10:17 +00001559 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001560 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1561
Gamze Abakafee36392019-10-03 11:17:24 +00001562 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001563 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001564 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001565 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
yasin saplibddc2d72022-02-08 13:10:17 +00001566 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001567 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1568 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1569 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1570 log.Fields{
1571 "tp-id": tpID,
1572 "path": tpPath})
1573 }
1574 switch tpInstance := tpInst.(type) {
1575 case *tp_pb.TechProfileInstance:
1576 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1577 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1578 }
1579 // Force cleanup scheduler/queues -- end
1580
1581 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301582 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001583 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301584 // return err
1585 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001586 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001587 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 +00001588 }
1589 return nil
1590}
1591
1592// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301593func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001594 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001595 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001596 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001597 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301598 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1599 log.Fields{
1600 "tp-id": tpID,
1601 "uni-port-name": uniPortName,
1602 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001603 }
1604 return nil
1605}
1606
David K. Bainbridge794735f2020-02-11 21:01:37 -08001607func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001608 var intfID uint32
1609 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1610 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1611 */
1612 if deviceFlow.AccessIntfId != -1 {
1613 intfID = uint32(deviceFlow.AccessIntfId)
1614 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001615 // We need to log the valid interface ID.
1616 // 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 +00001617 intfID = uint32(deviceFlow.NetworkIntfId)
1618 }
1619
Neha Sharma96b7bf22020-06-15 10:37:32 +00001620 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301621 "flow": *deviceFlow,
1622 "device-id": f.deviceHandler.device.Id,
1623 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001624 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001625
1626 st, _ := status.FromError(err)
1627 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001628 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001629 "err": err,
1630 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301631 "device-id": f.deviceHandler.device.Id,
1632 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001633 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301634 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001635
1636 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001637 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301638 log.Fields{"err": err,
1639 "device-flow": deviceFlow,
1640 "device-id": f.deviceHandler.device.Id,
1641 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001642 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001643 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001644 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301645 log.Fields{
1646 "flow": *deviceFlow,
1647 "device-id": f.deviceHandler.device.Id,
1648 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001649
yasin saplid0566272021-12-21 09:10:30 +00001650 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1651 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1652 return err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001653 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001654 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001655}
1656
Neha Sharma96b7bf22020-06-15 10:37:32 +00001657func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1658 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301659 log.Fields{
1660 "flow": *deviceFlow,
1661 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001662 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001663 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001664 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001665 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301666 log.Fields{
1667 "err": err,
1668 "deviceFlow": deviceFlow,
1669 "device-id": f.deviceHandler.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +05301670 // Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001671 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001672 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001673 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001674 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001675 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001676 "of-flow-id": ofFlowID,
1677 "flow": *deviceFlow,
1678 "device-id": f.deviceHandler.device.Id,
1679 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001680 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301681}
1682
David K. Bainbridge794735f2020-02-11 21:01:37 -08001683func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001684 classifierInfo := make(map[string]interface{})
1685 actionInfo := make(map[string]interface{})
1686
1687 classifierInfo[EthType] = uint32(LldpEthType)
1688 classifierInfo[PacketTagType] = Untagged
1689 actionInfo[TrapToHost] = true
1690
1691 // LLDP flow is installed to trap LLDP packets on the NNI port.
1692 // We manage flow_id resource pool on per PON port basis.
1693 // Since this situation is tricky, as a hack, we pass the NNI port
1694 // index (network_intf_id) as PON port Index for the flow_id resource
1695 // pool. Also, there is no ONU Id available for trapping LLDP packets
1696 // on NNI port, use onu_id as -1 (invalid)
1697 // ****************** CAVEAT *******************
1698 // This logic works if the NNI Port Id falls within the same valid
1699 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1700 // we need to have a re-look at this.
1701 // *********************************************
1702
1703 var onuID = -1
1704 var uniID = -1
1705 var gemPortID = -1
1706
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001707 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001708 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301709 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001710 }
yasin saplibddc2d72022-02-08 13:10:17 +00001711 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001712 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001713 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001714 return nil
yasin saplid0566272021-12-21 09:10:30 +00001715 } else if err != nil {
1716 logger.Errorw(ctx, "aborting-addLLDPFlow--flow-may-already-exist",
1717 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
1718 return err
Humera Kouser94d7a842019-08-25 19:04:32 -04001719 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001720
David K. Bainbridge794735f2020-02-11 21:01:37 -08001721 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1722 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301723 return olterrors.NewErrInvalidValue(
1724 log.Fields{
1725 "classifier": classifierInfo,
1726 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001727 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001728 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301729 log.Fields{
1730 "classifier": *classifierProto,
1731 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001732 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001733 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301734 return olterrors.NewErrInvalidValue(
1735 log.Fields{
1736 "action": actionInfo,
1737 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001738 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001739 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301740 log.Fields{
1741 "action": *actionProto,
1742 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001743
1744 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1745 OnuId: int32(onuID), // OnuId not required
1746 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001747 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001748 FlowType: Downstream,
1749 NetworkIntfId: int32(networkInterfaceID),
1750 GemportId: int32(gemPortID),
1751 Classifier: classifierProto,
1752 Action: actionProto,
1753 Priority: int32(flow.Priority),
1754 Cookie: flow.Cookie,
1755 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001756 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001757 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301758 log.Fields{
1759 "flow": downstreamflow,
1760 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001761 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001762 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301763 log.Fields{
1764 "device-id": f.deviceHandler.device.Id,
1765 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001766 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001767
David K. Bainbridge794735f2020-02-11 21:01:37 -08001768 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301769}
1770
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001771func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1772 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001773}
1774
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001775// getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001776func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001777 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1778 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1779 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001780 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301781 log.Fields{
1782 "intf-id": intfID,
1783 "onu-id": onuID,
1784 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001785 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001786 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301787 return nil, olterrors.NewErrNotFound("onu-child-device",
1788 log.Fields{
1789 "onu-id": onuID,
1790 "intf-id": intfID,
1791 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001792 }
khenaidoo106c61a2021-08-11 18:05:46 -04001793 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 +05301794 // better to ad the device to cache here.
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001795 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1796 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001797 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301798 log.Fields{
1799 "intf-id": intfID,
1800 "onu-id": onuID,
1801 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001802 }
1803
1804 return onuDev.(*OnuDevice), nil
1805}
1806
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001807// getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001808func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1809 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301810 log.Fields{
1811 "pon-port": intfID,
1812 "onu-id": onuID,
1813 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001814 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001815 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001816 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301817 return nil, olterrors.NewErrNotFound("onu",
1818 log.Fields{
1819 "interface-id": parentPortNo,
1820 "onu-id": onuID,
1821 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001822 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301823 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001824 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301825 log.Fields{
1826 "device-id": f.deviceHandler.device.Id,
1827 "child_device_id": onuDevice.Id,
1828 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301829 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301830}
1831
Neha Sharma96b7bf22020-06-15 10:37:32 +00001832func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1833 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301834 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001835 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301836 log.Fields{
1837 "intf-id": intfID,
1838 "onu-id": onuID,
1839 "uni-id": uniID,
1840 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001841 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301842 }
1843
khenaidoodc2116e2021-10-19 17:33:19 -04001844 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001845 DeviceId: onuDev.deviceID,
1846 UniId: uniID,
1847 TpInstancePath: tpPath,
1848 GemPortId: gemPortID,
1849 }
1850 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1851
1852 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301853 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1854 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001855 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1856 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301857 "onu-id": onuDev.deviceID,
1858 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001859 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301860 }
khenaidoo106c61a2021-08-11 18:05:46 -04001861
Neha Sharma96b7bf22020-06-15 10:37:32 +00001862 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301863 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001864 "msg": delGemPortMsg,
1865 "from-adapter": f.deviceHandler.device.Type,
1866 "to-adapter": onuDev.deviceType,
1867 "device-id": f.deviceHandler.device.Id,
1868 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301869 return nil
1870}
1871
Neha Sharma96b7bf22020-06-15 10:37:32 +00001872func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1873 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301874 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001875 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301876 log.Fields{
1877 "intf-id": intfID,
1878 "onu-id": onuID,
1879 "uni-id": uniID,
1880 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001881 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301882 }
1883
khenaidoodc2116e2021-10-19 17:33:19 -04001884 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001885 DeviceId: onuDev.deviceID,
1886 UniId: uniID,
1887 TpInstancePath: tpPath,
1888 AllocId: allocID,
1889 }
1890
Neha Sharma96b7bf22020-06-15 10:37:32 +00001891 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301892 log.Fields{
1893 "msg": *delTcontMsg,
1894 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001895
1896 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301897 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1898 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001899 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1900 "to-adapter": onuDev.adapterEndpoint,
1901 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301902 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001903 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301904 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001905 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301906 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001907 "msg": delTcontMsg,
1908 "device-id": f.deviceHandler.device.Id,
1909 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301910 return nil
1911}
1912
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001913// clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001914// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001915func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05301916 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool, nniIntfID uint32) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001917 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001918
Girish Gowdraa482f272021-03-24 23:04:19 -07001919 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
yasin saplibddc2d72022-02-08 13:10:17 +00001920 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001921 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1922 log.Fields{
1923 "tpPath": tpPath,
1924 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001925
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001926 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001927 if err != nil || techprofileInst == nil {
1928 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1929 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1930 if childDevice == nil {
1931 // happens when subscriber un-provision is immediately followed by child device delete
1932 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1933 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1934 return nil
1935 }
Elia Battiston2aaf4342022-02-07 15:16:38 +01001936 // If the tech profile is not found, since we want to delete it, there is no need to throw an error
1937 _ = olterrors.NewErrNotFound("tech-profile-in-kv-store",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001938 log.Fields{
1939 "tp-id": tpID,
Elia Battiston2aaf4342022-02-07 15:16:38 +01001940 "path": tpPath}, err).Log()
1941 return nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001942 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001943
1944 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001945 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001946 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001947 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1948 gemPortID := gemPort.GemportId
Girish Gowdrab4c33302022-03-18 15:07:38 -07001949 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, gemPortID)
1950 if err != nil {
1951 return err
1952 }
1953 used := false
1954 for _, id := range flowIDs {
1955 if flowID != id {
1956 used = true
1957 break
yasin sapli9e4c5092022-02-01 13:52:33 +00001958 }
Girish Gowdrab4c33302022-03-18 15:07:38 -07001959 }
1960 if used {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001961 for i, flowIDinMap := range flowIDs {
1962 if flowIDinMap == flowID {
1963 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
yasin saplibddc2d72022-02-08 13:10:17 +00001964 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, gemPortID, flowIDs); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001965 return err
1966 }
1967 break
1968 }
1969 }
1970 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1971 log.Fields{
1972 "gemport-id": gemPortID,
1973 "usedByFlows": flowIDs,
1974 "currentFlow": flowID,
1975 "device-id": f.deviceHandler.device.Id})
1976 allGemPortsFree = false
1977 }
1978 }
1979 if !allGemPortsFree {
1980 return nil
1981 }
1982 }
1983
1984 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 -08001985
1986 // 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 +00001987 switch techprofileInst := techprofileInst.(type) {
1988 case *tp_pb.TechProfileInstance:
Girish Gowdraf3728b12022-02-02 21:46:51 -08001989 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1990 gemPortID := gemPort.GemportId
yasin saplibddc2d72022-02-08 13:10:17 +00001991 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, uint32(onuID), gemPortID) // ignore error and proceed.
Girish Gowdraf3728b12022-02-02 21:46:51 -08001992
yasin saplibddc2d72022-02-08 13:10:17 +00001993 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, gemPortID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08001994 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
1995 log.Fields{
1996 "err": err,
1997 "intf": intfID,
1998 "onu-id": onuID,
1999 "uni-id": uniID,
2000 "device-id": f.deviceHandler.device.Id,
2001 "gemport-id": gemPortID})
2002 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002003 }
2004 // Remove queues at OLT in upstream and downstream direction
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302005 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 +05302006 if err := f.RemoveQueues(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002007 logger.Warn(ctx, err)
2008 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302009 schedQ.direction = tp_pb.Direction_DOWNSTREAM
2010 if err := f.RemoveQueues(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002011 logger.Warn(ctx, err)
2012 }
2013 }
2014
2015 switch techprofileInst := techprofileInst.(type) {
2016 case *tp_pb.TechProfileInstance:
2017 // 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 +05302018 schedQ := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2019 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQ)
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002020 if !allocExists {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002021 // all alloc object references removed, remove upstream scheduler
yasin saplibddc2d72022-02-08 13:10:17 +00002022 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302023 if err := f.RemoveScheduler(ctx, schedQ); err != nil {
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002024 logger.Warn(ctx, err)
2025 }
2026 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002027 // remove alloc id from resource pool by setting the 'freeFromResourcePool' to true
yasin saplibddc2d72022-02-08 13:10:17 +00002028 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, true)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002029 } else {
2030 // just remove meter reference for the upstream direction for the current pon/onu/uni
2031 // 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 +05302032 if err := f.removeMeterReference(ctx, "upstream", schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002033 return err
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002034 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002035 // setting 'freeFromResourcePool' to false in resourceMgr.FreeAllocID will only remove alloc-id data for the given pon/onu/uni
2036 // but still preserve it on the resource pool.
yasin saplibddc2d72022-02-08 13:10:17 +00002037 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, false)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002038 }
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002039
Girish Gowdraf3728b12022-02-02 21:46:51 -08002040 // 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 +05302041 schedQ.direction = tp_pb.Direction_DOWNSTREAM
yasin saplibddc2d72022-02-08 13:10:17 +00002042 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302043 if err := f.RemoveScheduler(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002044 logger.Warn(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002045 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002046 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002047 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002048 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002049 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002050 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302051 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002052 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302053 "onu-id": onuID,
2054 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002055 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002056 "alloc-id": techprofileInst.AllocId,
2057 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002058 }
yasin saplibddc2d72022-02-08 13:10:17 +00002059 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.AllocId, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302060 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
2061 logger.Warn(ctx, err)
2062 }
2063 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2064 logger.Warn(ctx, err)
2065 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002066 default:
2067 logger.Errorw(ctx, "error-unknown-tech",
2068 log.Fields{
2069 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002070 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002071
2072 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
2073 switch techprofileInst := techprofileInst.(type) {
2074 case *tp_pb.TechProfileInstance:
2075 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2076 // Delete the gem port on the ONU.
2077 if sendDeleteGemRequest {
2078 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId, tpPath); err != nil {
2079 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2080 log.Fields{
2081 "err": err,
2082 "intfID": intfID,
2083 "onu-id": onuID,
2084 "uni-id": uniID,
2085 "device-id": f.deviceHandler.device.Id,
2086 "gemport-id": gemPort.GemportId})
2087 }
yasin saplibddc2d72022-02-08 13:10:17 +00002088 f.resourceMgr.FreeGemPortID(ctx, uint32(onuID), uint32(uniID), gemPort.GemportId)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002089 }
2090 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302091 // Delete the tp instance and the techprofileid for onu at the end
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302092 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2093 logger.Warn(ctx, err)
2094 }
2095 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
2096 logger.Warn(ctx, err)
2097 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002098 }
2099
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302100 return nil
2101}
2102
David K. Bainbridge794735f2020-02-11 21:01:37 -08002103// nolint: gocyclo
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302104func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string, nni_port uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002105 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302106 log.Fields{
2107 "flowDirection": flowDirection,
2108 "flow": *flow,
2109 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002110
2111 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002112 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002113 }
2114
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302115 var ethType, ipProto, inPort uint32
2116 for _, field := range flows.GetOfbFields(flow) {
2117 if field.Type == flows.IP_PROTO {
2118 ipProto = field.GetIpProto()
2119 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"ipProto": ipProto})
2120 } else if field.Type == flows.ETH_TYPE {
2121 ethType = field.GetEthType()
2122 logger.Debugw(ctx, "field-type-eth-type", log.Fields{"ethType": ethType})
2123 } else if field.Type == flows.IN_PORT {
2124 inPort = field.GetPort()
2125 logger.Debugw(ctx, "field-type-in-port", log.Fields{"inPort": inPort})
2126 }
2127 }
2128 portType := plt.IntfIDToPortTypeName(inPort)
2129 if (ethType == uint32(LldpEthType) || ipProto == uint32(IPProtoDhcp) || ipProto == uint32(IgmpProto)) &&
2130 (portType == voltha.Port_ETHERNET_NNI) {
2131 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: -1, OnuId: -1, UniId: -1, TechProfileId: 0, FlowType: Downstream}
2132 logger.Debugw(ctx, "nni-trap-flow-to-be-deleted", log.Fields{"flow": flow})
2133 return f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id)
2134 // No more processing needed for trap from nni flows.
2135 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302136
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302137 portNum, Intf, onu, uni, _, _, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302138 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002139 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002140 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302141 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002142 onuID := int32(onu)
2143 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002144 tpID, err := getTpIDFromFlow(ctx, flow)
2145 if err != nil {
2146 return olterrors.NewErrNotFound("tp-id",
2147 log.Fields{
2148 "flow": flow,
2149 "intf-id": Intf,
2150 "onu-id": onuID,
2151 "uni-id": uniID,
2152 "device-id": f.deviceHandler.device.Id}, err)
2153 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302154
Neha Sharma96b7bf22020-06-15 10:37:32 +00002155 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302156 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002157 "flow-id": flow.Id,
2158 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302159 "onu-id": onuID,
2160 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302161
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002162 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2163 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002164 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2165 return err
2166 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002167
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302168 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true, nni_port); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002169 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2170 "flow-id": flow.Id,
2171 "device-id": f.deviceHandler.device.Id,
2172 "onu-id": onuID,
2173 "intf": Intf,
2174 "err": err,
2175 })
2176 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302177 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002178
Girish Gowdra82c80982021-03-26 16:22:02 -07002179 // 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 +00002180 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, uint32(onuID), uint32(uniID), tpID, false); err != nil {
Girish Gowdra82c80982021-03-26 16:22:02 -07002181 return err
2182 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002183 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002184}
2185
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002186// RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002187func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Matteo Scandolof16389e2021-05-18 00:47:08 +00002188 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302189 var direction string
2190 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002191
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302192 for _, action := range flows.GetActions(flow) {
2193 if action.Type == flows.OUTPUT {
2194 if out := action.GetOutput(); out != nil {
2195 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002196 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302197 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002198 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002199 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002200 }
2201 }
2202 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002203
2204 if flows.HasGroup(flow) {
2205 direction = Multicast
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002206 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302207 direction = Upstream
2208 } else {
2209 direction = Downstream
2210 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302211
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302212 var nni_port uint32
2213 if direction == Upstream {
2214 if !plt.IsControllerBoundFlow(actionInfo[Output].(uint32)) {
2215 nni_port = actionInfo[Output].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2216 }
2217 } else {
2218 classifierInfo := make(map[string]interface{})
2219 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
2220 nni_port = classifierInfo[InPort].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2221 }
2222
Girish Gowdracefae192020-03-19 18:14:10 -07002223 // Serialize flow removes on a per subscriber basis
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302224 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction, nni_port)
Girish Gowdracefae192020-03-19 18:14:10 -07002225
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002226 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002227}
2228
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002229// isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
Esin Karamanae41e2b2019-12-17 18:13:13 +00002230func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002231 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002232 if ethType, ok := classifierInfo[EthType]; ok {
2233 if ethType.(uint32) == IPv4EthType {
2234 if ipProto, ok := classifierInfo[IPProto]; ok {
2235 if ipProto.(uint32) == IgmpProto {
2236 return true
2237 }
2238 }
2239 }
2240 }
2241 }
2242 return false
2243}
2244
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002245// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002246func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002247 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2248 // The device itself is going to be reset as part of deletion. So nothing to be done.
2249 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2250 return nil
2251 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002252 // Step1 : Fill flowControlBlock
2253 // Step2 : Push the flowControlBlock to ONU channel
2254 // Step3 : Wait on response channel for response
2255 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002256 startTime := time.Now()
2257 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002258 errChan := make(chan error)
2259 flowCb := flowControlBlock{
2260 ctx: ctx,
2261 addFlow: addFlow,
2262 flow: flow,
2263 flowMetadata: flowMetadata,
2264 errChan: &errChan,
2265 }
2266 inPort, outPort := getPorts(flow)
2267 var onuID uint32
2268 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002269 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002270 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002271 if f.flowHandlerRoutineActive[onuID] {
2272 // inPort or outPort is InvalidPort for trap-from-nni flows.
2273 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2274 // Send the flowCb on the ONU flow channel
2275 f.incomingFlows[onuID] <- flowCb
2276 // Wait on the channel for flow handlers return value
2277 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002278 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002279 return err
2280 }
2281 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2282 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002283}
2284
2285// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2286// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002287func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002288 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002289 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002290 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002291 // block on the channel to receive an incoming flow
2292 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002293 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002294 if flowCb.addFlow {
2295 logger.Info(flowCb.ctx, "adding-flow-start")
2296 startTime := time.Now()
2297 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2298 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2299 // Pass the return value over the return channel
2300 *flowCb.errChan <- err
2301 } else {
2302 logger.Info(flowCb.ctx, "removing-flow-start")
2303 startTime := time.Now()
2304 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2305 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2306 // Pass the return value over the return channel
2307 *flowCb.errChan <- err
2308 }
2309 case <-stopHandler:
2310 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2311 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002312 }
2313 }
2314}
2315
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002316// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002317func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002318 for i, v := range f.stopFlowHandlerRoutine {
2319 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002320 select {
2321 case v <- true:
2322 case <-time.After(time.Second * 5):
2323 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2324 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002325 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002326 f.stopFlowHandlerRoutine[i] = nil
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002327 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002328 f.stopFlowHandlerRoutine = nil
2329
2330 if f.incomingFlows != nil {
2331 for k := range f.incomingFlows {
2332 if f.incomingFlows[k] != nil {
2333 f.incomingFlows[k] = nil
2334 }
2335 }
2336 f.incomingFlows = nil
2337 }
2338
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002339 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002340 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2341}
2342
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002343// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302344// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002345func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002346 classifierInfo := make(map[string]interface{})
2347 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002348 var UsMeterID uint32
2349 var DsMeterID uint32
2350
Neha Sharma96b7bf22020-06-15 10:37:32 +00002351 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302352 log.Fields{
2353 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002354 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002355 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002356
Neha Sharma96b7bf22020-06-15 10:37:32 +00002357 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002358 if err != nil {
2359 // Error logging is already done in the called function
2360 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002361 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302362 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002363
Esin Karamanccb714b2019-11-29 15:02:06 +00002364 if flows.HasGroup(flow) {
2365 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002366 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002367 }
2368
manikkaraj k17652a72019-05-06 09:06:36 -04002369 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002370 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002371 if err != nil {
2372 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002373 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002374 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002375
Neha Sharma96b7bf22020-06-15 10:37:32 +00002376 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302377 log.Fields{
2378 "classifierinfo_inport": classifierInfo[InPort],
2379 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002380 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002381
Humera Kouser94d7a842019-08-25 19:04:32 -04002382 if ethType, ok := classifierInfo[EthType]; ok {
2383 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002384 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002385 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002386 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002387 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002388 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002389 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2390 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2391 }
2392 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002393 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002394 if ipProto, ok := classifierInfo[IPProto]; ok {
2395 if ipProto.(uint32) == IPProtoDhcp {
2396 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302397 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002398 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002399 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002400 }
2401 }
2402 }
2403 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002404 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002405 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002406 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002407 }
A R Karthick1f85b802019-10-11 05:06:05 +00002408
yasin saplibddc2d72022-02-08 13:10:17 +00002409 f.resourceMgr.AddUniPortToOnuInfo(ctx, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002410
Girish Gowdra6071f382021-12-14 12:52:04 +05302411 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002412 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302413 return olterrors.NewErrNotFound("tpid-for-flow",
2414 log.Fields{
2415 "flow": flow,
2416 "intf-id": IntfID,
2417 "onu-id": onuID,
2418 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002419 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002420 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302421 log.Fields{
Girish Gowdra6071f382021-12-14 12:52:04 +05302422 "tp-id": tpID,
Shrey Baid26912972020-04-16 21:02:31 +05302423 "intf-id": intfID,
2424 "onu-id": onuID,
2425 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002426 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002427 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002428 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302429 if err := f.validateMeter(ctx, Upstream, UsMeterID, intfID, onuID, uniID, tpID); err != nil {
2430 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2431 return err
2432 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002433 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002434 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002435 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302436 if err := f.validateMeter(ctx, Downstream, DsMeterID, intfID, onuID, uniID, tpID); err != nil {
2437 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2438 return err
2439 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002440 }
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302441
2442 var nni_port uint32
2443 if plt.IsUpstream(actionInfo[Output].(uint32)) {
2444 if !plt.IsControllerBoundFlow(actionInfo[Output].(uint32)) {
2445 nni_port = actionInfo[Output].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2446 }
2447 } else {
2448 nni_port = classifierInfo[InPort].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2449 }
2450
2451 return f.processAddFlow(ctx, intfID, nni_port, onuID, uniID, portNo, classifierInfo, actionInfo, flow, tpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002452}
Girish Gowdra3d633032019-12-10 16:37:05 +05302453
Esin Karamanccb714b2019-11-29 15:02:06 +00002454// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002455func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302456 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002457 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302458 "classifier-info": classifierInfo,
2459 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002460
Esin Karaman65409d82020-03-18 10:58:18 +00002461 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002462 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002463 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002464 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002465
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002466 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002467
David K. Bainbridge794735f2020-02-11 21:01:37 -08002468 onuID := NoneOnuID
Esin Karamanccb714b2019-11-29 15:02:06 +00002469
yasin saplibddc2d72022-02-08 13:10:17 +00002470 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002471 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002472 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002473 return nil
yasin saplid0566272021-12-21 09:10:30 +00002474 } else if err != nil {
2475 logger.Errorw(ctx, "aborting-handleFlowWithGroup--flow-may-already-exist",
2476 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
2477 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00002478 }
yasin saplid0566272021-12-21 09:10:30 +00002479
David K. Bainbridge794735f2020-02-11 21:01:37 -08002480 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2481 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002482 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002483 }
2484 groupID := actionInfo[GroupID].(uint32)
2485 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002486 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002487 FlowType: Multicast,
2488 NetworkIntfId: int32(networkInterfaceID),
2489 GroupId: groupID,
2490 Classifier: classifierProto,
2491 Priority: int32(flow.Priority),
2492 Cookie: flow.Cookie}
2493
Kent Hagermane6ff1012020-07-14 15:07:53 -04002494 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002495 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002496 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002497 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
Akash Kankanala041a2122024-10-16 15:49:22 +05302498 // get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002499 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302500 // calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002501 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002502 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002503 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302504 // cached group can be removed now
Kent Hagermane6ff1012020-07-14 15:07:53 -04002505 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002506 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002507 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002508 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002509
David K. Bainbridge794735f2020-02-11 21:01:37 -08002510 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002511}
2512
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002513// 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 +00002514func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2515 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002516 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002517 if err != nil {
2518 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2519 }
2520 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002521 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002522
2523 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2524 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002525}
2526
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002527// sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002528func (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 +00002529 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302530 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002531 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302532 log.Fields{
2533 "intf-id": intfID,
2534 "onu-id": onuID,
2535 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002536 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302537 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002538 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002539
yasin saplibddc2d72022-02-08 13:10:17 +00002540 tpPath := f.getTPpath(ctx, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002541 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002542 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002543 UniId: uniID,
2544 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002545 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002546 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002547 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002548
2549 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2550 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302551 return olterrors.NewErrCommunication("send-techprofile-download-request",
2552 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002553 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302554 "to-adapter": onuDev.deviceType,
2555 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002556 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002557 }
nikesh.krishnan81ec7442023-10-31 17:19:34 +05302558 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpid": TpID})
Manikkaraj k884c1242019-04-11 16:26:42 +05302559 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302560}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002561
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002562// GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302563func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002564 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002565
2566 if packetIn.IntfType == "pon" {
2567 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002568 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002569 onuID, uniID := packetIn.OnuId, packetIn.UniId
2570 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 +00002571
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002572 if packetIn.PortNo != 0 {
2573 logicalPortNum = packetIn.PortNo
2574 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002575 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002576 }
2577 // 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 +00002578 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002579 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002580 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002581 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002582
2583 if logger.V(log.DebugLevel) {
2584 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2585 log.Fields{
2586 "logical-port-num": logicalPortNum,
2587 "intf-type": packetIn.IntfType,
2588 "packet": hex.EncodeToString(packetIn.Pkt),
2589 })
2590 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002591 return logicalPortNum, nil
2592}
2593
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002594// GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002595func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002596 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002597
2598 ctag, priority, err := getCTagFromPacket(ctx, packet)
2599 if err != nil {
2600 return 0, err
2601 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302602
Esin Karaman7fb80c22020-07-16 14:23:33 +00002603 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002604 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002605 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002606 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002607 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302608 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002609 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302610 log.Fields{
2611 "pktinkey": pktInkey,
2612 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002613
2614 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002615 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302616 // 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 +00002617 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302618 if err == nil {
2619 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002620 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302621 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002622 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002623 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302624 log.Fields{
2625 "pktinkey": pktInkey,
2626 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302627 return gemPortID, nil
2628 }
2629 }
Shrey Baid26912972020-04-16 21:02:31 +05302630 return uint32(0), olterrors.NewErrNotFound("gem-port",
2631 log.Fields{
2632 "pktinkey": pktInkey,
2633 "gem": gemPortID}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002634}
2635
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002636func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2637 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002638 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002639 classifier[PacketTagType] = DoubleTag
2640 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002641 /* We manage flowId resource pool on per PON port basis.
2642 Since this situation is tricky, as a hack, we pass the NNI port
2643 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002644 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002645 on NNI port, use onu_id as -1 (invalid)
2646 ****************** CAVEAT *******************
2647 This logic works if the NNI Port Id falls within the same valid
2648 range of PON Port Ids. If this doesn't work for some OLT Vendor
2649 we need to have a re-look at this.
2650 *********************************************
2651 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002652 onuID := -1
2653 uniID := -1
2654 gemPortID := -1
2655 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002656 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302657 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302658 return olterrors.NewErrNotFound("nni-intreface-id",
2659 log.Fields{
2660 "classifier": classifier,
2661 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002662 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302663 }
2664
yasin saplibddc2d72022-02-08 13:10:17 +00002665 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002666 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002667 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002668 return nil
yasin saplid0566272021-12-21 09:10:30 +00002669 } else if err != nil {
2670 logger.Errorw(ctx, "aborting-addTrapFlowOnNNI--flow-may-already-exist",
2671 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2672 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002673 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002674
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002675 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2676 log.Fields{
2677 "classifier": classifier,
2678 "action": action,
2679 "flowId": logicalFlow.Id,
2680 "intf-id": networkInterfaceID})
2681
David K. Bainbridge794735f2020-02-11 21:01:37 -08002682 classifierProto, err := makeOpenOltClassifierField(classifier)
2683 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002684 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002685 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002686 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002687 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002688 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002689 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002690 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002691 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002692 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2693 OnuId: int32(onuID), // OnuId not required
2694 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002695 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002696 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002697 AllocId: int32(allocID), // AllocId not used
2698 NetworkIntfId: int32(networkInterfaceID),
2699 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002700 Classifier: classifierProto,
2701 Action: actionProto,
2702 Priority: int32(logicalFlow.Priority),
2703 Cookie: logicalFlow.Cookie,
2704 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002705 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002706 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002707 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002708 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002709 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002710}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002711
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002712// getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
Esin Karamanae41e2b2019-12-17 18:13:13 +00002713func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2714 var packetType string
2715 ovid, ivid := false, false
2716 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2717 vid := vlanID & VlanvIDMask
2718 if vid != ReservedVlan {
2719 ovid = true
2720 }
2721 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07002722
2723 // The classifierInfo[Metadata] is set for the following flows
2724 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
2725 // - Mcast flow that points to a group in the action/treatment
2726 // This value, when present and valid (not 0 and not 4096), is interpreted as below
2727 // - inner vid for a double tagged packet in the datapath flow
2728 // - outer vid for a single tagged packet in the datapath flow
2729 // - inner vid in the mcast flow that points to a group
2730
2731 // It is to be noted though that for DT FTTH downstream table0 flow, the classifierInfo[Metadata] is absent.
2732 // And consequently the ivid is not set to true. This will result in packetType being set to singleTag which is not true
2733 // Interestingly enough, this function `getPacketTypeFromClassifiers` is called only by Mcast flow handlers and
2734 // 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 +00002735 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2736 vid := uint32(metadata)
2737 if vid != ReservedVlan {
2738 ivid = true
2739 }
2740 }
2741 if ovid && ivid {
2742 packetType = DoubleTag
2743 } else if !ovid && !ivid {
2744 packetType = Untagged
2745 } else {
2746 packetType = SingleTag
2747 }
2748 return packetType
2749}
2750
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002751// addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002752func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002753 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002754 action := make(map[string]interface{})
2755 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2756 action[TrapToHost] = true
2757 /* We manage flowId resource pool on per PON port basis.
2758 Since this situation is tricky, as a hack, we pass the NNI port
2759 index (network_intf_id) as PON port Index for the flowId resource
2760 pool. Also, there is no ONU Id available for trapping packets
2761 on NNI port, use onu_id as -1 (invalid)
2762 ****************** CAVEAT *******************
2763 This logic works if the NNI Port Id falls within the same valid
2764 range of PON Port Ids. If this doesn't work for some OLT Vendor
2765 we need to have a re-look at this.
2766 *********************************************
2767 */
2768 onuID := -1
2769 uniID := -1
2770 gemPortID := -1
2771 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002772 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002773 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302774 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002775 "classifier": classifier,
2776 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002777 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002778 }
yasin saplibddc2d72022-02-08 13:10:17 +00002779 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002780 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002781 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002782 return nil
yasin saplid0566272021-12-21 09:10:30 +00002783 } else if err != nil {
2784 logger.Errorw(ctx, "aborting-addIgmpTrapFlowOnNNI--flow-may-already-exist",
2785 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2786 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002787 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002788
David K. Bainbridge794735f2020-02-11 21:01:37 -08002789 classifierProto, err := makeOpenOltClassifierField(classifier)
2790 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002791 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002792 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002793 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002794 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002795 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002796 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002797 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002798 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002799 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2800 OnuId: int32(onuID), // OnuId not required
2801 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002802 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002803 FlowType: Downstream,
2804 AllocId: int32(allocID), // AllocId not used
2805 NetworkIntfId: int32(networkInterfaceID),
2806 GemportId: int32(gemPortID), // GemportId not used
2807 Classifier: classifierProto,
2808 Action: actionProto,
2809 Priority: int32(logicalFlow.Priority),
2810 Cookie: logicalFlow.Cookie,
2811 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002812 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002813 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002814 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002815 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002816
David K. Bainbridge794735f2020-02-11 21:01:37 -08002817 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002818}
2819
salmansiddiqui7ac62132019-08-22 03:58:50 +00002820func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2821 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302822 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002823 }
2824 if Dir == tp_pb.Direction_UPSTREAM {
2825 return "upstream", nil
2826 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2827 return "downstream", nil
2828 }
2829 return "", nil
2830}
2831
Kent Hagermane6ff1012020-07-14 15:07:53 -04002832// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302833func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002834 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002835 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002836 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002837 intfID := args[IntfID]
2838 onuID := args[OnuID]
2839 uniID := args[UniID]
2840 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002841 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002842 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002843 gemToAes := make(map[uint32]bool)
2844
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002845 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002846 var direction = tp_pb.Direction_UPSTREAM
2847 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002848 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002849 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002850 attributes = TpInst.UpstreamGemPortAttributeList
2851 } else {
2852 attributes = TpInst.DownstreamGemPortAttributeList
2853 direction = tp_pb.Direction_DOWNSTREAM
2854 }
2855 default:
2856 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002857 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002858 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002859
2860 if len(gemPorts) == 1 {
2861 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002862 gemPortID = gemPorts[0]
2863 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002864 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2865 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002866 pBitMap := attributes[idx].PbitMap
2867 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2868 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2869 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002870 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002871 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2872 if pbitSet == pbit1 {
2873 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2874 pbitToGem[pcp] = gemID
2875 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002876 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002877 }
2878 }
2879 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002880 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2881 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2882 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002883 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002884 }
2885
Akash Kankanala041a2122024-10-16 15:49:22 +05302886 flowContext := &flowContext{classifierInfo, actionInfo, flow, pbitToGem, gemToAes, intfID, onuID, uniID, portNo, allocID, gemPortID, tpID}
Gamze Abaka7650be62021-02-26 10:50:36 +00002887
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302888 var nni_port uint32
2889 if plt.IsUpstream(actionInfo[Output].(uint32)) {
2890 if !plt.IsControllerBoundFlow(actionInfo[Output].(uint32)) {
2891 nni_port = actionInfo[Output].(uint32) & 0x1f // convert e.g. 16777220 to port 4 (starting with 0)
2892 }
2893 } else {
2894 nni_port = classifierInfo[InPort].(uint32) & 0x1f // convert e.g. 16777220 to port 4 (starting with 0)
2895 }
2896
salmansiddiqui7ac62132019-08-22 03:58:50 +00002897 if ipProto, ok := classifierInfo[IPProto]; ok {
2898 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002899 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002900 "tp-id": tpID,
2901 "alloc-id": allocID,
2902 "intf-id": intfID,
2903 "onu-id": onuID,
2904 "uni-id": uniID,
2905 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302906 // Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002907 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002908 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002909 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 +05302910 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002911 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002912 }
Girish Gowdra32625212020-04-29 11:26:35 -07002913 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002914 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302915 log.Fields{
2916 "intf-id": intfID,
2917 "onu-id": onuID,
2918 "uni-id": uniID,
2919 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002920 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002921 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002922 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 +05302923 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002924 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002925 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002926 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002927 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002928 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002929 }
2930 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002931 if ethType.(uint32) == EapEthType {
2932 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002933 "intf-id": intfID,
2934 "onu-id": onuID,
2935 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002936 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002937 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002938 var vlanID uint32
2939 if val, ok := classifierInfo[VlanVid]; ok {
2940 vlanID = (val.(uint32)) & VlanvIDMask
2941 } else {
2942 vlanID = DefaultMgmtVlan
2943 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002944 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002945 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002946 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 +05302947 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002948 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002949 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002950 } else if ethType.(uint32) == PPPoEDEthType {
2951 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2952 "tp-id": tpID,
2953 "alloc-id": allocID,
2954 "intf-id": intfID,
2955 "onu-id": onuID,
2956 "uni-id": uniID,
2957 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302958 // Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002959 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002960 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002961 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 +05302962 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002963 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002964 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002965 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002966 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002967 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002968 "intf-id": intfID,
2969 "onu-id": onuID,
2970 "uni-id": uniID,
2971 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302972 // Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002973 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002974 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002975 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 +05302976 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002977 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002978 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002979 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002980 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002981 "intf-id": intfID,
2982 "onu-id": onuID,
2983 "uni-id": uniID,
2984 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302985 // Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002986 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002987 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002988 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 +05302989 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002990 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002991 }
2992 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002993 return olterrors.NewErrInvalidValue(log.Fields{
2994 "intf-id": intfID,
2995 "onu-id": onuID,
2996 "uni-id": uniID,
2997 "classifier": classifierInfo,
2998 "action": actionInfo,
2999 "flow": flow},
3000 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003001 }
3002 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04003003 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003004 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003005 logger.Warn(ctx, err)
3006 }
3007 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003008 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00003009}
3010
Gamze Abakacb0e6772021-06-10 08:32:12 +00003011func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003012 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
3013 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
3014 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 +05303015 for i := 0; i < len(tpInstances); i++ {
3016 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00003017 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003018 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Girish Gowdraf3728b12022-02-02 21:46:51 -08003019 logger.Debugw(ctx, "alloc-is-in-use-on-another-uni",
Gamze Abakacb0e6772021-06-10 08:32:12 +00003020 log.Fields{
3021 "device-id": f.deviceHandler.device.Id,
3022 "intfID": sq.intfID,
3023 "onuID": sq.onuID,
3024 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003025 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00003026 })
3027 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303028 }
3029 }
3030 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003031 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003032}
3033
Neha Sharma96b7bf22020-06-15 10:37:32 +00003034func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003035 for _, field := range flows.GetOfbFields(flow) {
3036 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003037 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003038 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003039 } else if field.Type == flows.ETH_DST {
3040 classifierInfo[EthDst] = field.GetEthDst()
Girish Gowdraffa52e52022-02-16 15:48:10 -08003041 logger.Debug(ctx, "field-type-eth-dst", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
3042 } else if field.Type == flows.ETH_SRC {
3043 classifierInfo[EthSrc] = field.GetEthSrc()
3044 logger.Debug(ctx, "field-type-eth-src", log.Fields{"classifierInfo[ETH_SRC]": classifierInfo[EthSrc].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003045 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003046 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003047 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003048 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003049 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003050 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003051 } else if field.Type == flows.VLAN_VID {
Andrea Campanellafaa42152021-10-28 11:50:56 +05303052 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3053 if field.GetVlanVid() != ReservedVlan {
3054 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3055 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3056 }
Scott Baker355d1742019-10-24 10:57:52 -07003057 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003058 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003059 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003060 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003061 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003062 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003063 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003064 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003065 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003066 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003067 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003068 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003069 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003070 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003071 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003072 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003073 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003074 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003075 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003076 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003077 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003078 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003079 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003080 return
3081 }
3082 }
3083}
3084
Neha Sharma96b7bf22020-06-15 10:37:32 +00003085func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003086 for _, action := range flows.GetActions(flow) {
3087 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003088 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003089 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003090 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003091 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003092 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003093 }
Scott Baker355d1742019-10-24 10:57:52 -07003094 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003095 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003096 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003097 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003098 if out := action.GetPush(); out != nil {
3099 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003100 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003101 } else {
3102 actionInfo[PushVlan] = true
3103 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003104 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303105 log.Fields{
3106 "push-tpid": actionInfo[TPID].(uint32),
3107 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003108 }
3109 }
Scott Baker355d1742019-10-24 10:57:52 -07003110 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003111 if out := action.GetSetField(); out != nil {
3112 if field := out.GetField(); field != nil {
3113 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003114 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003115 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003116 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3117 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003118 }
3119 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003120 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003121 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003122 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003123 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003124 }
3125 }
3126 return nil
3127}
3128
Neha Sharma96b7bf22020-06-15 10:37:32 +00003129func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003130 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003131 fieldtype := ofbField.GetType()
3132 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003133 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3134 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003135 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003136 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003137 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003138 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003139 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3140 pcp := ofbField.GetVlanPcp()
3141 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003142 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003143 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003144 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003145 }
3146 }
3147}
3148
Neha Sharma96b7bf22020-06-15 10:37:32 +00003149func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003150 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003151 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003152 } else {
3153 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003154 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003155 }
3156}
3157
Neha Sharma96b7bf22020-06-15 10:37:32 +00003158func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003159 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003160 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003161 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003162 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003163 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003164 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003165 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303166 log.Fields{
3167 "newinport": classifierInfo[InPort].(uint32),
3168 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003169 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303170 return olterrors.NewErrNotFound("child-in-port",
3171 log.Fields{
3172 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3173 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003174 }
3175 }
3176 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003177 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003178 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003179 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003180 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003181 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003182 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303183 log.Fields{
3184 "newoutport": actionInfo[Output].(uint32),
3185 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003186 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303187 return olterrors.NewErrNotFound("out-port",
3188 log.Fields{
3189 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3190 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003191 }
3192 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003193 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003194 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003195 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003196 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303197 log.Fields{
3198 "newinport": actionInfo[Output].(uint32),
3199 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003200 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303201 return olterrors.NewErrNotFound("nni-port",
3202 log.Fields{
3203 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3204 "in-port": classifierInfo[InPort].(uint32),
3205 "out-port": actionInfo[Output].(uint32),
3206 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003207 }
3208 }
3209 }
3210 return nil
3211}
Gamze Abakafee36392019-10-03 11:17:24 +00003212
Neha Sharma96b7bf22020-06-15 10:37:32 +00003213func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003214 /* Metadata 8 bytes:
3215 Most Significant 2 Bytes = Inner VLAN
3216 Next 2 Bytes = Tech Profile ID(TPID)
3217 Least Significant 4 Bytes = Port ID
3218 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3219 subscriber related flows.
3220 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003221 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003222 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003223 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003224 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003225 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003226 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003227}
3228
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003229func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003230 for _, sliceElement := range slice {
3231 if sliceElement == item {
3232 return slice
3233 }
3234 }
3235 return append(slice, item)
3236}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303237
yasin saplie87d4bd2021-12-06 09:04:03 +00003238func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3239 for _, sliceElement := range slice {
3240 if sliceElement == item {
3241 return slice
3242 }
3243 }
3244 return append(slice, item)
3245}
3246
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303247// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003248func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003249 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303250 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003251 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003252 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003253 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003254 log.Fields{
3255 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003256 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003257 return uint32(0), err
3258 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003259 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303260 return intfID, nil
3261 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003262 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003263 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003264 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003265 log.Fields{
3266 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003267 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003268 return uint32(0), err
3269 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003270 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303271 return intfID, nil
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05303272 } else if portType == voltha.Port_ETHERNET_UNI {
3273 if _, ok := action[Output]; ok {
3274 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
3275 if err != nil {
3276 logger.Debugw(ctx, "invalid-action-port-number",
3277 log.Fields{
3278 "port-number": action[Output].(uint32),
3279 "err": err})
3280 return uint32(0), nil
3281 }
3282 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
3283 return intfID, nil
3284 } else {
3285 logger.Debugw(ctx, "action-port-number-empty",
3286 log.Fields{
3287 "action": action})
3288 return uint32(0), nil
3289 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303290 }
3291 return uint32(0), nil
3292}
3293
3294// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003295func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3296 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3297 if err != nil {
3298 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3299 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3300 return
3301 }
3302 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003303
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003304 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003305 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003306 f.packetInGemPortLock.RUnlock()
3307
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303308 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003309 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003310 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 +05303311 log.Fields{
3312 "pktinkey": pktInkey,
3313 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003314 return
3315 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303316 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003317 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003318 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003319 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003320
npujarec5762e2020-01-01 14:08:48 +05303321 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003322 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 +05303323 log.Fields{
3324 "pktinkey": pktInkey,
3325 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303326}
3327
Joey Armstrong3f0e2422023-07-05 18:25:41 -04003328// getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003329func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3330 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003331 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003332 return 0, 0, errors.New("invalid packet length")
3333 }
3334 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3335 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3336
3337 var index int8
3338 if outerEthType == 0x8100 {
3339 if innerEthType == 0x8100 {
3340 // q-in-q 802.1ad or 802.1q double tagged packet.
3341 // get the inner vlanId
3342 index = 18
3343 } else {
3344 index = 14
3345 }
3346 priority := (packet[index] >> 5) & 0x7
Akash Kankanala041a2122024-10-16 15:49:22 +05303347 // 13 bits composes vlanId value
Esin Karaman7fb80c22020-07-16 14:23:33 +00003348 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3349 return vlan, priority, nil
3350 }
3351 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3352 return 0, 0, nil
3353}
3354
Joey Armstrong3f0e2422023-07-05 18:25:41 -04003355// clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
Girish Gowdra9602eb42020-09-09 15:50:39 -07003356// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003357func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003358 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003359 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3360 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003361 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003362 "flow-id": flow.Id,
3363 "device-id": f.deviceHandler.device.Id})
3364 // Remove from device
3365 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3366 // DKB
3367 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3368 log.Fields{
3369 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003370 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003371 return err
3372 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003373
3374 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003375}
3376
khenaidoodc2116e2021-10-19 17:33:19 -04003377func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003378 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003379 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003380 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003381 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003382 }
3383
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003384 switch tpInst := tpInst.(type) {
3385 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003386 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003387 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003388 DeviceId: onuDeviceID,
3389 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003390 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003391 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003392 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003393 case *tp_pb.EponTechProfileInstance:
3394 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003395 DeviceId: onuDeviceID,
3396 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003397 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003398 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003399 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003400 default:
3401 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003402 }
khenaidoodc2116e2021-10-19 17:33:19 -04003403 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003404 DeviceId: onuDeviceID,
3405 UniId: uniID,
3406 TpInstancePath: tpPath,
3407 TechTpInstance: nil,
3408 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003409}
3410
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003411// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3412func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003413 intfID := sq.intfID
3414 onuID := sq.onuID
3415 uniID := sq.uniID
3416 tpID := sq.tpID
3417
3418 var reverseDirection string
3419 if sq.direction == tp_pb.Direction_UPSTREAM {
3420 reverseDirection = "downstream"
3421 } else {
3422 reverseDirection = "upstream"
3423 }
3424
3425 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
yasin saplibddc2d72022-02-08 13:10:17 +00003426 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, onuID, uniID, tpID); KvStoreMeter != nil {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003427 return
3428 }
3429
3430 // revert-delete tech-profile instance and delete tech profile id for onu
3431 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})
3432 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3433 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
yasin saplibddc2d72022-02-08 13:10:17 +00003434 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, onuID, uniID, tpID)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003435
3436 // free gem/alloc
3437 switch techprofileInst := sq.tpInst.(type) {
3438 case *tp_pb.TechProfileInstance:
3439 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
yasin saplibddc2d72022-02-08 13:10:17 +00003440 f.resourceMgr.FreeGemPortID(ctx, onuID, uniID, gem.GemportId)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003441 }
yasin saplibddc2d72022-02-08 13:10:17 +00003442 f.resourceMgr.FreeAllocID(ctx, onuID, uniID, techprofileInst.UsScheduler.AllocId, true)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003443 }
3444}
3445
3446// revertSchduler is called when CreateQueues request fails
3447func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3448 // revert scheduler
3449 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})
3450 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
3451 IntfId: sq.intfID, OnuId: sq.onuID,
3452 UniId: sq.uniID, PortNo: sq.uniPort,
3453 TrafficScheds: TrafficSched})
3454}
Girish Gowdra6071f382021-12-14 12:52:04 +05303455
3456// validateMeter validates if there is a meter mismatch for the given direction. It also clears the stale meter if the reference count is zero
3457func (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 +00003458 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, onuID, uniID, tpID)
Girish Gowdra6071f382021-12-14 12:52:04 +05303459 if err != nil {
3460 return olterrors.NewErrNotFound("meter",
3461 log.Fields{"intf-id": intfID,
3462 "onu-id": onuID,
3463 "uni-id": uniID,
3464 "device-id": f.deviceHandler.device.Id}, err)
3465 }
3466
3467 if meterInfo != nil {
3468 // If RefCnt become 0 clear the meter information from the DB.
3469 if meterInfo.MeterID != meterID && meterInfo.RefCnt == 0 {
yasin saplibddc2d72022-02-08 13:10:17 +00003470 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, onuID, uniID, tpID); err != nil {
Girish Gowdra6071f382021-12-14 12:52:04 +05303471 return err
3472 }
3473 } else if meterInfo.MeterID != meterID {
3474 logger.Errorw(ctx, "meter-mismatch-for-direction",
3475 log.Fields{"direction": direction,
3476 "kv-store-meter-id": meterInfo.MeterID,
3477 "meter-id-in-flow": meterID,
3478 "device-id": f.deviceHandler.device.Id})
3479 return olterrors.NewErrInvalidValue(log.Fields{
3480 "unsupported": "meter-id",
3481 "kv-store-meter-id": meterInfo.MeterID,
3482 "meter-id-in-flow": meterID,
3483 "device-id": f.deviceHandler.device.Id}, nil)
3484 }
3485 }
3486 return nil
3487}
Girish Gowdraf3728b12022-02-02 21:46:51 -08003488
3489func (f *OpenOltFlowMgr) removeMeterReference(ctx context.Context, direction string, sq schedQueue) error {
3490 /* After we successfully remove the scheduler configuration on the OLT device,
3491 * delete the meter id on the KV store.
3492 */
yasin saplibddc2d72022-02-08 13:10:17 +00003493 err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Girish Gowdraf3728b12022-02-02 21:46:51 -08003494 if err != nil {
3495 return olterrors.NewErrAdapter("unable-to-remove-meter",
3496 log.Fields{
3497 "onu": sq.onuID,
3498 "device-id": f.deviceHandler.device.Id,
3499 "intf-id": sq.intfID,
3500 "onu-id": sq.onuID,
3501 "uni-id": sq.uniID,
3502 "uni-port": sq.uniPort}, err)
3503 }
3504 logger.Debugw(ctx, "removed-meter-from-KV-store-successfully",
3505 log.Fields{
3506 "dir": direction,
3507 "device-id": f.deviceHandler.device.Id,
3508 "intf-id": sq.intfID,
3509 "onu-id": sq.onuID,
3510 "uni-id": sq.uniID,
3511 "uni-port": sq.uniPort})
3512 return err
3513}