blob: 7389cb74c2a9f3a9bb0922517bc48d82858d1ee6 [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
167 onuID uint32
168 uniID uint32
169 tpID uint32
170 uniPort uint32
Gamze Abakafee36392019-10-03 11:17:24 +0000171 meterID uint32
Gamze Abakafee36392019-10-03 11:17:24 +0000172}
173
Gamze Abaka7650be62021-02-26 10:50:36 +0000174type flowContext struct {
Akash Kankanala041a2122024-10-16 15:49:22 +0530175 classifier map[string]interface{}
176 action map[string]interface{}
177 logicalFlow *ofp.OfpFlowStats
178 pbitToGem map[uint32]uint32
179 gemToAes map[uint32]bool
Gamze Abaka7650be62021-02-26 10:50:36 +0000180 intfID uint32
181 onuID uint32
182 uniID uint32
183 portNo uint32
Gamze Abaka7650be62021-02-26 10:50:36 +0000184 allocID uint32
185 gemPortID uint32
186 tpID uint32
Gamze Abaka7650be62021-02-26 10:50:36 +0000187}
188
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700189// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
190// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
191// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
192// flow and processes it serially
193type flowControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400194 ctx context.Context // Flow handler context
khenaidoodc2116e2021-10-19 17:33:19 -0400195 flow *ofp.OfpFlowStats // Flow message
196 flowMetadata *ofp.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
197 errChan *chan error // channel to report the Flow handling error
Akash Kankanala041a2122024-10-16 15:49:22 +0530198 addFlow bool // if true flow to be added, else removed
Esin Karamanccb714b2019-11-29 15:02:06 +0000199}
200
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400201// OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530202type OpenOltFlowMgr struct {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700203 techprofile tp.TechProfileIf
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700204 deviceHandler *DeviceHandler
205 grpMgr *OpenOltGroupMgr
206 resourceMgr *rsrcMgr.OpenOltResourceMgr
207
Akash Kankanala041a2122024-10-16 15:49:22 +0530208 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 // packet in gem port local cache
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700209
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700210 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
211 // 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 -0700212 incomingFlows []chan flowControlBlock
213 stopFlowHandlerRoutine []chan bool
214 flowHandlerRoutineActive []bool
Akash Kankanala041a2122024-10-16 15:49:22 +0530215 packetInGemPortLock sync.RWMutex
216
217 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
manikkaraj kbf256be2019-03-25 00:13:48 +0530218}
219
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000220// CloseKVClient closes open KV clients
221func (f *OpenOltFlowMgr) CloseKVClient(ctx context.Context) {
222 if f.techprofile != nil {
223 f.techprofile.CloseKVClient(ctx)
224 }
225}
226
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400227// NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700228func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000229 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530230 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530231 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530232
manikkaraj kbf256be2019-03-25 00:13:48 +0530233 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700234 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700235 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530236 flowMgr.resourceMgr = rMgr
yasin saplid0566272021-12-21 09:10:30 +0000237 // dh.totalPonPorts is reserved for NNI trap flows. It doesn't need a tech profile
238 if ponPortIdx != dh.totalPonPorts {
239 if err = flowMgr.populateTechProfileForCurrentPonPort(ctx); err != nil {
240 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
241 return nil
242 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530243 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530244 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700245
246 // Create a slice of buffered channels for handling concurrent flows per ONU.
247 // 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 -0700248 flowMgr.incomingFlows = make([]chan flowControlBlock, plt.MaxOnusPerPon+1)
249 flowMgr.stopFlowHandlerRoutine = make([]chan bool, plt.MaxOnusPerPon+1)
250 flowMgr.flowHandlerRoutineActive = make([]bool, plt.MaxOnusPerPon+1)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700251 for i := range flowMgr.incomingFlows {
252 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
Girish Gowdraae56c722021-11-22 14:31:11 -0800253 flowMgr.stopFlowHandlerRoutine[i] = make(chan bool)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700254 // Spin up a go routine to handling incoming flows (add/remove).
255 // There will be on go routine per ONU.
256 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700257 flowMgr.flowHandlerRoutineActive[i] = true
258 go flowMgr.perOnuFlowHandlerRoutine(i, flowMgr.incomingFlows[i], flowMgr.stopFlowHandlerRoutine[i])
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700259 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700260
Akash Kankanala041a2122024-10-16 15:49:22 +0530261 // load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700262 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000263 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530264 return &flowMgr
265}
266
Kent Hagermane6ff1012020-07-14 15:07:53 -0400267func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
yasin saplid0566272021-12-21 09:10:30 +0000268 // In case of nni trap flow
269 if deviceFlow.AccessIntfId == -1 {
yasin saplibddc2d72022-02-08 13:10:17 +0000270 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), flowFromCore)
yasin saplid0566272021-12-21 09:10:30 +0000271 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700272 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
273 // 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 +0000274 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700275 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
276 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
277 for _, gemPort := range deviceFlow.PbitToGemport {
yasin saplibddc2d72022-02-08 13:10:17 +0000278 if err := f.resourceMgr.RegisterFlowIDForGem(ctx, gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700279 return err
280 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700281 }
Gamze Abakafee36392019-10-03 11:17:24 +0000282 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700283 return nil
284}
285
Girish Gowdra9602eb42020-09-09 15:50:39 -0700286func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000287 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
khenaidoodc2116e2021-10-19 17:33:19 -0400288 UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000289 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530290 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700291 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530292
Neha Sharma96b7bf22020-06-15 10:37:32 +0000293 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530294 "device-id": f.deviceHandler.device.Id,
295 "intf-id": intfID,
296 "onu-id": onuID,
297 "uni-id": uniID,
298 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700299 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530300 "action": actionInfo,
301 "usmeter-iD": UsMeterID,
302 "dsmeter-iD": DsMeterID,
303 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400304 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
305 // is because the flow is an NNI flow and there would be no onu resources associated with it
306 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400307 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200308 cause := "no-onu-id-for-flow"
309 fields := log.Fields{
310 "onu": onuID,
311 "port-no": portNo,
312 "classifer": classifierInfo,
313 "action": actionInfo,
314 "device-id": f.deviceHandler.device.Id}
315 logger.Errorw(ctx, cause, fields)
316 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530317 }
318
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700319 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000320 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530321 "uni": uni,
322 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530323
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700324 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
325 "device-id": f.deviceHandler.device.Id,
326 "intf-id": intfID,
327 "onu-id": onuID,
328 "uni-id": uniID,
329 "port-no": portNo,
330 "classifier": classifierInfo,
331 "action": actionInfo,
332 "usmeter-id": UsMeterID,
333 "dsmeter-id": DsMeterID,
334 "tp-id": TpID})
335 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
336 if allocID == 0 || gemPorts == nil || TpInst == nil {
337 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
338 return olterrors.NewErrNotFound(
339 "alloc-id-gem-ports-tp-unavailable",
340 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400341 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700342 args := make(map[string]uint32)
343 args[IntfID] = intfID
344 args[OnuID] = onuID
345 args[UniID] = uniID
346 args[PortNo] = portNo
347 args[AllocID] = allocID
348
349 /* Flows can be added specific to gemport if p-bits are received.
350 * If no pbit mentioned then adding flows for all gemports
351 */
Gamze Abaka6d0a64f2021-11-18 08:08:33 +0000352 return f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530353}
354
salmansiddiqui7ac62132019-08-22 03:58:50 +0000355// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Girish Gowdraf3728b12022-02-02 21:46:51 -0800356// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530357func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
nikesh.krishnan81ec7442023-10-31 17:19:34 +0530358 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530359 log.Fields{"dir": sq.direction,
360 "intf-id": sq.intfID,
361 "onu-id": sq.onuID,
362 "uni-id": sq.uniID,
363 "tp-id": sq.tpID,
364 "meter-id": sq.meterID,
365 "tp-inst": sq.tpInst,
366 "flowmetadata": sq.flowMetadata,
367 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400368
Girish Gowdra6071f382021-12-14 12:52:04 +0530369 direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000370 if err != nil {
371 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400372 }
373
Girish Gowdraf3728b12022-02-02 21:46:51 -0800374 var TrafficShaping *tp_pb.TrafficShapingInfo
375 if sq.flowMetadata == nil || len(sq.flowMetadata.Meters) != 1 {
376 return olterrors.NewErrInvalidValue(log.Fields{
377 "reason": "invalid-meter-config",
378 "meter-id": sq.meterID,
379 "device-id": f.deviceHandler.device.Id}, nil)
380 }
381
382 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
383 return olterrors.NewErrInvalidValue(log.Fields{
384 "reason": "invalid-meter-config",
385 "meter-id": sq.meterID,
386 "device-id": f.deviceHandler.device.Id}, nil)
387 }
388
389 var SchedCfg *tp_pb.SchedulerConfig
390 if sq.direction == tp_pb.Direction_UPSTREAM {
391 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
392 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
393 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
394 }
395 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
396 TrafficSched[0].TechProfileId = sq.tpID
397
Manikkaraj kb1d51442019-07-23 10:41:02 -0400398 /* Lets make a simple assumption that if the meter-id is present on the KV store,
399 * then the scheduler and queues configuration is applied on the OLT device
400 * in the given direction.
401 */
yasin saplibddc2d72022-02-08 13:10:17 +0000402 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400403 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530404 return olterrors.NewErrNotFound("meter",
405 log.Fields{"intf-id": sq.intfID,
406 "onu-id": sq.onuID,
407 "uni-id": sq.uniID,
408 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400409 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000410
Girish Gowdraf3728b12022-02-02 21:46:51 -0800411 // update reference count and return if the meter was already installed before
Girish Gowdra6071f382021-12-14 12:52:04 +0530412 if meterInfo != nil && meterInfo.MeterID == sq.meterID {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800413 logger.Infow(ctx, "scheduler-already-created-for-direction",
Girish Gowdra6071f382021-12-14 12:52:04 +0530414 log.Fields{"device-id": f.deviceHandler.device.Id, "direction": direction, "meter-id": sq.meterID})
yasin saplibddc2d72022-02-08 13:10:17 +0000415 if err = f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, direction, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800416 return err
417 }
418
419 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); allocExists {
420 // Alloc object was already created as part of flow setup on another uni of the onu for the same service.
421 // Just create gem ports and traffic queues on the current uni for the given service
422 logger.Infow(ctx, "alloc in use on another uni, schedulers already created, creating queues only",
423 log.Fields{"intf-id": sq.intfID,
424 "onu-id": sq.onuID,
425 "uni-id": sq.uniID,
426 "tp-id": sq.tpID,
427 "device-id": f.deviceHandler.device.Id})
428 // The upstream scheduler is already created. We only need to create the queues
429 // If there are multiple upstream flows on a given uni, then it is possible that
430 // we call pushTrafficQueues multiple times, but that is OK as BAL returns OK.
431 // TODO: Find better mechanism to not duplicate request.
432 if err = f.pushTrafficQueues(ctx, sq, TrafficSched); err != nil {
433 return olterrors.NewErrAdapter("failure-pushing-traffic-queues-to-device",
434 log.Fields{"intf-id": sq.intfID,
435 "direction": sq.direction,
436 "device-id": f.deviceHandler.device.Id}, err)
437 }
438 } else {
439 logger.Infow(ctx, "alloc not in use on another uni, only meter ref cnt updated",
440 log.Fields{"intf-id": sq.intfID,
441 "onu-id": sq.onuID,
442 "uni-id": sq.uniID,
443 "tp-id": sq.tpID,
444 "device-id": f.deviceHandler.device.Id})
445 }
446 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400447 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000448
Neha Sharma96b7bf22020-06-15 10:37:32 +0000449 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530450 log.Fields{
451 "meter-id": sq.meterID,
Girish Gowdra6071f382021-12-14 12:52:04 +0530452 "direction": direction,
Shrey Baid26912972020-04-16 21:02:31 +0530453 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000454
Girish Gowdraa482f272021-03-24 23:04:19 -0700455 found := false
456 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000457 if sq.flowMetadata != nil {
458 for _, meter := range sq.flowMetadata.Meters {
459 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700460 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700461 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 +0000462 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700463 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530464 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700465 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400466 break
467 }
468 }
469 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000470 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400471 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700472 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530473 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800474 "reason": "Could-not-get-meterbands-from-flowMetadata",
475 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530476 "meter-id": sq.meterID,
477 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478 }
Gamze Abaka01174422021-03-10 06:55:27 +0000479
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700480 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530481 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
482 log.Fields{"intf-id": sq.intfID,
483 "direction": sq.direction,
484 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400485 }
486
salmansiddiqui7ac62132019-08-22 03:58:50 +0000487 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400488 * store the meter id on the KV store, for further reference.
489 */
yasin saplibddc2d72022-02-08 13:10:17 +0000490 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530491 return olterrors.NewErrAdapter("failed-updating-meter-id",
492 log.Fields{"onu-id": sq.onuID,
493 "meter-id": sq.meterID,
494 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400495 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000496 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Girish Gowdra6071f382021-12-14 12:52:04 +0530497 log.Fields{"direction": direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700498 "meter-info": meterInfo,
499 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400500 return nil
501}
502
Girish Gowdraf3728b12022-02-02 21:46:51 -0800503func (f *OpenOltFlowMgr) pushTrafficQueues(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
504 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
505 if err != nil {
506 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
507 log.Fields{"intf-id": sq.intfID,
508 "direction": sq.direction,
509 "device-id": f.deviceHandler.device.Id}, err)
510 }
511 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
512 log.Fields{"direction": sq.direction,
513 "traffic-queues": trafficQueues,
514 "device-id": f.deviceHandler.device.Id})
515 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
516 UniId: sq.uniID, PortNo: sq.uniPort,
517 TrafficQueues: trafficQueues,
518 TechProfileId: TrafficSched[0].TechProfileId}
Akash Kankanala041a2122024-10-16 15:49:22 +0530519 if _, err = f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800520 if len(queues.TrafficQueues) > 1 {
521 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
522 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
523 }
524 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
525 }
526 return err
527}
528
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700529func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700530 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000531
532 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530533 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
534 log.Fields{"intf-id": sq.intfID,
535 "direction": sq.direction,
536 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000537 }
538
Gamze Abakacb0e6772021-06-10 08:32:12 +0000539 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
540 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
541 log.Fields{
542 "direction": sq.direction,
543 "TrafficScheds": TrafficSched,
544 "device-id": f.deviceHandler.device.Id,
545 "intfID": sq.intfID,
546 "onuID": sq.onuID,
547 "uniID": sq.uniID})
548 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
549 IntfId: sq.intfID, OnuId: sq.onuID,
550 UniId: sq.uniID, PortNo: sq.uniPort,
551 TrafficScheds: TrafficSched}); err != nil {
552 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
553 }
554 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
555 "direction": sq.direction,
556 "traffic-queues": trafficQueues,
557 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000558 }
559
560 // On receiving the CreateTrafficQueues request, the driver should create corresponding
561 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000562 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530563 log.Fields{"direction": sq.direction,
564 "traffic-queues": trafficQueues,
565 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000566 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
567 UniId: sq.uniID, PortNo: sq.uniPort,
568 TrafficQueues: trafficQueues,
569 TechProfileId: TrafficSched[0].TechProfileId}
570 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
571 if len(queues.TrafficQueues) > 1 {
572 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
573 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
574 }
575 f.revertScheduler(ctx, sq, TrafficSched)
Shrey Baid26912972020-04-16 21:02:31 +0530576 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000577 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000578 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530579 "direction": sq.direction,
580 "traffic-queues": trafficQueues,
581 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000582
Esin Karamanccb714b2019-11-29 15:02:06 +0000583 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700584 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000585 if len(multicastTrafficQueues) > 0 {
Akash Kankanala041a2122024-10-16 15:49:22 +0530586 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present { // assumed that there is only one queue per PON for the multicast service
587 // the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
588 // just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000589 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000590 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700591 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000592 gemPortID: multicastQueuePerPonPort.GemportId,
593 servicePriority: multicastQueuePerPonPort.Priority,
594 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700595 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Akash Kankanala041a2122024-10-16 15:49:22 +0530596 // also store the queue info in kv store
yasin saplibddc2d72022-02-08 13:10:17 +0000597 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700598 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400599 return err
600 }
Shrey Baid26912972020-04-16 21:02:31 +0530601
Neha Sharma96b7bf22020-06-15 10:37:32 +0000602 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000603 }
604 }
605 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000606 return nil
607}
608
Girish Gowdraf3728b12022-02-02 21:46:51 -0800609// RemoveQueues removes the traffic queues from the device based on the given schedQueue info
610func (f *OpenOltFlowMgr) RemoveQueues(ctx context.Context, sq schedQueue) error {
611 var err error
612 logger.Infow(ctx, "removing-queue-in-olt",
613 log.Fields{
614 "direction": sq.direction,
615 "intf-id": sq.intfID,
616 "onu-id": sq.onuID,
617 "uni-id": sq.uniID,
618 "uni-port": sq.uniPort,
619 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400620
Girish Gowdraf3728b12022-02-02 21:46:51 -0800621 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
622 if err != nil {
623 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
624 log.Fields{
625 "intf-id": sq.intfID,
626 "direction": sq.direction,
627 "device-id": f.deviceHandler.device.Id}, err)
628 }
629
630 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
631 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
632 UniId: sq.uniID, PortNo: sq.uniPort,
633 TrafficQueues: TrafficQueues,
634 TechProfileId: sq.tpID}); err != nil {
635 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
636 log.Fields{
637 "intf-id": sq.intfID,
638 "traffic-queues": TrafficQueues,
639 "device-id": f.deviceHandler.device.Id}, err)
640 }
641 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
642
643 return err
644}
645
646// RemoveScheduler removes the traffic scheduler from the device based on the given schedQueue info
647func (f *OpenOltFlowMgr) RemoveScheduler(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400648 var Direction string
649 var SchedCfg *tp_pb.SchedulerConfig
650 var err error
Girish Gowdraf3728b12022-02-02 21:46:51 -0800651 logger.Infow(ctx, "removing-scheduler-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530652 log.Fields{
653 "direction": sq.direction,
654 "intf-id": sq.intfID,
655 "onu-id": sq.onuID,
656 "uni-id": sq.uniID,
657 "uni-port": sq.uniPort,
658 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000659 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700660 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400661 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000662 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700663 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400664 Direction = "downstream"
665 }
666
Girish Gowdraa482f272021-03-24 23:04:19 -0700667 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 -0400668
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700669 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000670 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000671
Girish Gowdraf3728b12022-02-02 21:46:51 -0800672 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
673 IntfId: sq.intfID, OnuId: sq.onuID,
674 UniId: sq.uniID, PortNo: sq.uniPort,
675 TrafficScheds: TrafficSched}); err != nil {
676 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530677 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800678 "intf-id": sq.intfID,
679 "traffic-schedulers": TrafficSched,
680 "onu-id": sq.onuID,
681 "uni-id": sq.uniID,
682 "uni-port": sq.uniPort}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000683 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400684
Girish Gowdraf3728b12022-02-02 21:46:51 -0800685 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
686 log.Fields{"device-id": f.deviceHandler.device.Id,
687 "intf-id": sq.intfID,
688 "onu-id": sq.onuID,
689 "uni-id": sq.uniID,
690 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400691
Girish Gowdraf3728b12022-02-02 21:46:51 -0800692 if sq.direction == tp_pb.Direction_UPSTREAM {
693 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
694 // Delete the TCONT on the ONU.
695 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
yasin saplibddc2d72022-02-08 13:10:17 +0000696 tpPath := f.getTPpath(ctx, uni, sq.tpID)
Akash Kankanala041a2122024-10-16 15:49:22 +0530697 if err = f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800698 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Gamze Abakacb0e6772021-06-10 08:32:12 +0000699 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800700 "intf": sq.intfID,
701 "onu-id": sq.onuID,
702 "uni-id": sq.uniID,
703 "device-id": f.deviceHandler.device.Id,
704 "alloc-id": allocID})
Gamze Abakacb0e6772021-06-10 08:32:12 +0000705 }
706 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000707
708 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400709 * delete the meter id on the KV store.
710 */
Girish Gowdraf3728b12022-02-02 21:46:51 -0800711 err = f.removeMeterReference(ctx, Direction, sq)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400712 return err
713}
714
Girish Gowdra197acc12021-08-16 10:59:45 -0700715// We are trying to force remove the schedulers and queues here if one exists for the given key.
716// We ignore any errors encountered in the process. The errors most likely are encountered when
717// the schedulers and queues are already cleared for the given key.
718func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
Girish Gowdra197acc12021-08-16 10:59:45 -0700719 var schedCfg *tp_pb.SchedulerConfig
Girish Gowdra197acc12021-08-16 10:59:45 -0700720 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
721 log.Fields{
722 "direction": sq.direction,
723 "intf-id": sq.intfID,
724 "onu-id": sq.onuID,
725 "uni-id": sq.uniID,
726 "uni-port": sq.uniPort,
727 "tp-id": sq.tpID,
728 "device-id": f.deviceHandler.device.Id})
729 if sq.direction == tp_pb.Direction_UPSTREAM {
730 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
731 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
732 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
733 }
734
735 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
736 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
737 TrafficSched[0].TechProfileId = sq.tpID
738
739 // Remove traffic queues. Ignore any errors, just log them.
740 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
741 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
742 "direction": sq.direction,
743 "intf-id": sq.intfID,
744 "onu-id": sq.onuID,
745 "uni-id": sq.uniID,
746 "uni-port": sq.uniPort,
747 "tp-id": sq.tpID,
748 "device-id": f.deviceHandler.device.Id,
749 "err": err})
750 } else {
751 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
752 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
753 UniId: sq.uniID, PortNo: sq.uniPort,
754 TrafficQueues: TrafficQueues,
755 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
756 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
757 "direction": sq.direction,
758 "intf-id": sq.intfID,
759 "onu-id": sq.onuID,
760 "uni-id": sq.uniID,
761 "uni-port": sq.uniPort,
762 "tp-id": sq.tpID,
763 "device-id": f.deviceHandler.device.Id,
764 "err": err})
Girish Gowdra197acc12021-08-16 10:59:45 -0700765 } else {
766 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
767 "direction": sq.direction,
768 "intf-id": sq.intfID,
769 "onu-id": sq.onuID,
770 "uni-id": sq.uniID,
771 "uni-port": sq.uniPort,
772 "tp-id": sq.tpID})
773 }
774 }
775
776 // Remove traffic schedulers. Ignore any errors, just log them.
Akash Kankanala041a2122024-10-16 15:49:22 +0530777 if _, err := f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Gowdra197acc12021-08-16 10:59:45 -0700778 IntfId: sq.intfID, OnuId: sq.onuID,
779 UniId: sq.uniID, PortNo: sq.uniPort,
780 TrafficScheds: TrafficSched}); err != nil {
781 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
782 "direction": sq.direction,
783 "intf-id": sq.intfID,
784 "onu-id": sq.onuID,
785 "uni-id": sq.uniID,
786 "uni-port": sq.uniPort,
787 "tp-id": sq.tpID,
788 "device-id": f.deviceHandler.device.Id,
789 "err": err})
790 } else {
791 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
792 "direction": sq.direction,
793 "intf-id": sq.intfID,
794 "onu-id": sq.onuID,
795 "uni-id": sq.uniID,
796 "uni-port": sq.uniPort,
797 "tp-id": sq.tpID})
798 }
799}
800
Gamze Abakafee36392019-10-03 11:17:24 +0000801// This function allocates tconts and GEM ports for an ONU
khenaidoodc2116e2021-10-19 17:33:19 -0400802func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID 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 +0000803 var allocIDs []uint32
804 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530805 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530806 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000807 var err error
yasin saplibddc2d72022-02-08 13:10:17 +0000808 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, onuID, uniID)
809 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, onuID, uniID)
810 tpPath := f.getTPpath(ctx, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530811
Neha Sharma96b7bf22020-06-15 10:37:32 +0000812 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530813 "intf-id": intfID,
814 "onu-id": onuID,
815 "uni-id": uniID,
816 "device-id": f.deviceHandler.device.Id,
817 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530818
Manikkaraj kb1d51442019-07-23 10:41:02 -0400819 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700820 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000821 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000822 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530823 log.Fields{
824 "path": tpPath,
825 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700826 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000827 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530828 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000829 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530830 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700831 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530832 "tp-id": TpID,
833 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000834 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530835 }
yasin saplibddc2d72022-02-08 13:10:17 +0000836 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700837 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400838 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530839 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000840 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530841 log.Fields{
842 "uni": uni,
843 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530844 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530845 }
Gamze Abakafee36392019-10-03 11:17:24 +0000846
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700847 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700848 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700849 if UsMeterID != 0 {
850 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
851 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
852 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000853 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700854 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700855 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700856 "onu-id": onuID,
857 "uni-id": uniID,
858 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700859 "meter-id": UsMeterID,
860 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000861 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700862 return 0, nil, nil
863 }
864 }
865 if DsMeterID != 0 {
866 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
867 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
868 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000869 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700870 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700871 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700872 "onu-id": onuID,
873 "uni-id": uniID,
874 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700875 "meter-id": DsMeterID,
876 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000877 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700878 return 0, nil, nil
879 }
880 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700881 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700882 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700883 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700884 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700885 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000886
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700887 if tpInstanceExists {
888 return allocID, gemPortIDs, techProfileInstance
889 }
890
891 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700892 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700893 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000894 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700895 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700896 "intf-id": intfID,
897 "onu-id": onuID,
898 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700899 "alloc-ids": allocIDs,
900 "gemports": allgemPortIDs,
901 "device-id": f.deviceHandler.device.Id})
902 // Send Tconts and GEM ports to KV store
903 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530904 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400905 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700906 // CreateSchedulerQueues for EPON needs to be implemented here
907 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700908 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700909 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700910 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700911 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700912 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700913
914 if tpInstanceExists {
915 return allocID, gemPortIDs, techProfileInstance
916 }
917
918 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700919 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700920 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000921 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700922 log.Fields{
923 "alloc-ids": allocIDs,
924 "gemports": allgemPortIDs,
925 "device-id": f.deviceHandler.device.Id})
926 // Send Tconts and GEM ports to KV store
927 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
928 return allocID, gemPortIDs, techProfileInstance
929 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000930 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700931 log.Fields{
932 "tpInst": tpInst})
933 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530934 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530935}
936
npujarec5762e2020-01-01 14:08:48 +0530937func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000938 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530939 log.Fields{
940 "intf-id": intfID,
941 "onu-id": onuID,
942 "uni-id": uniID,
943 "alloc-id": allocID,
944 "gemport-ids": gemPortIDs,
945 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530946 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
yasin saplibddc2d72022-02-08 13:10:17 +0000947 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, onuID, uniID, allocID); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000948 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 +0530949 }
yasin saplibddc2d72022-02-08 13:10:17 +0000950 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, onuID, uniID, gemPortIDs); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000951 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 +0530952 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700953
Neha Sharma96b7bf22020-06-15 10:37:32 +0000954 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 -0400955 for _, gemPort := range gemPortIDs {
yasin saplibddc2d72022-02-08 13:10:17 +0000956 if err := f.resourceMgr.AddGemToOnuGemInfo(ctx, onuID, gemPort); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000957 logger.Errorw(ctx, "error-while-uploading-onugeminfos-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "gemPort": gemPort})
958 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400959 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530960}
961
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700962func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530963 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000964 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700965 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
966 var err error
pnalmas937a24d2025-01-16 18:48:30 +0530967 f.techprofile, err = tp.NewTechProfile(ctx, intfID, f.resourceMgr.DeviceID, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700968 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
969 if err != nil || f.techprofile == nil {
970 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
971 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
972 }
973 logger.Debugw(ctx, "init-tech-profile-done",
974 log.Fields{
975 "intf-id": intfID,
976 "device-id": f.deviceHandler.device.Id})
977 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700978 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530979 }
980 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700981 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
982 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 +0530983}
984
Gamze Abaka7650be62021-02-26 10:50:36 +0000985func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Girish Gowdraffa52e52022-02-16 15:48:10 -0800986 flowContext.classifier[PacketTagType] = SingleTag
987 // extract the cvid/inner-vid from the write metadata
988 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
989 if writeMetadata != 0 {
990 // Writemetadata field is 8 bytes
991 // cvid is on the outer most two bytes of the write metadata
992 cvid := (writeMetadata & 0xffff000000000000) >> 48
993 // if the cvid does not match the classifier vlan, then this indicates it is a double tagged packet
994 if cvid != flowContext.classifier[VlanVid] && cvid != 0 {
995 flowContext.classifier[PacketTagType] = DoubleTag
996 }
997 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000998 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530999 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001000 "uplinkClassifier": flowContext.classifier,
1001 "uplinkAction": flowContext.action})
1002 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301003}
1004
Gamze Abaka7650be62021-02-26 10:50:36 +00001005func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
1006 downlinkClassifier := flowContext.classifier
1007 downlinkAction := flowContext.action
Girish Gowdraffa52e52022-02-16 15:48:10 -08001008 // default to single tag. If we detect an inner cvid from write-metadata, then we mark the PacketTagType as DoubleTag
1009 downlinkClassifier[PacketTagType] = SingleTag
1010 // extract the cvid/inner-vid from the write metadata
1011 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
1012 if writeMetadata != 0 {
1013 // Writemetadata field is 8 bytes
1014 // cvid is on the outer most two bytes of the write metadata
1015 if cvid := (writeMetadata & 0xffff000000000000) >> 48; cvid != 0 {
1016 downlinkClassifier[PacketTagType] = DoubleTag
1017 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301018 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001019 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301020 log.Fields{
1021 "downlinkClassifier": downlinkClassifier,
1022 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001023
Girish Gowdraffa52e52022-02-16 15:48:10 -08001024 // If Pop Vlan action is specified, set the vlan to be popped from the classifier vlan match field.
1025 // The matched vlan is the one that is getting popped.
1026 if val, ok := downlinkAction[PopVlan]; ok && val.(bool) {
1027 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1028 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
1029 if ok {
1030 downlinkAction[VlanVid] = dlClVid & 0xfff
1031 }
Girish Gowdra26f344b2019-10-23 14:39:13 +05301032 }
1033
Gamze Abaka7650be62021-02-26 10:50:36 +00001034 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301035}
1036
Gamze Abaka7650be62021-02-26 10:50:36 +00001037func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001038 intfID := flowContext.intfID
1039 onuID := flowContext.onuID
1040 uniID := flowContext.uniID
1041 classifier := flowContext.classifier
1042 action := flowContext.action
1043 allocID := flowContext.allocID
1044 gemPortID := flowContext.gemPortID
1045 tpID := flowContext.tpID
1046 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001047 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301048 log.Fields{
1049 "intf-id": intfID,
1050 "onu-id": onuID,
1051 "uni-id": uniID,
1052 "device-id": f.deviceHandler.device.Id,
1053 "classifier": classifier,
1054 "action": action,
1055 "direction": direction,
1056 "alloc-id": allocID,
1057 "gemport-id": gemPortID,
1058 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001059
yasin saplibddc2d72022-02-08 13:10:17 +00001060 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001061 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001062 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301063 log.Fields{
1064 "device-id": f.deviceHandler.device.Id,
1065 "intf-id": intfID,
1066 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001067 return nil
yasin saplid0566272021-12-21 09:10:30 +00001068 } else if err != nil {
1069 logger.Errorw(ctx, "aborting-addSymmetricDataPathFlow--flow-may-already-exist",
1070 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1071 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301072 }
yasin saplid0566272021-12-21 09:10:30 +00001073
David K. Bainbridge794735f2020-02-11 21:01:37 -08001074 classifierProto, err := makeOpenOltClassifierField(classifier)
1075 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301076 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301077 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001078 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301079 log.Fields{
1080 "classifier": *classifierProto,
1081 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001082 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001083 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301084 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301085 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001086 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301087 log.Fields{
1088 "action": *actionProto,
1089 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001090 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301091 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301092 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001093 log.Fields{
1094 "classifier": classifier,
1095 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301096 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001097 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301098 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001099
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001100 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001101 OnuId: int32(onuID),
1102 UniId: int32(uniID),
1103 FlowId: logicalFlow.Id,
1104 FlowType: direction,
1105 AllocId: int32(allocID),
1106 NetworkIntfId: int32(networkIntfID),
1107 GemportId: int32(gemPortID),
1108 Classifier: classifierProto,
1109 Action: actionProto,
1110 Priority: int32(logicalFlow.Priority),
1111 Cookie: logicalFlow.Cookie,
1112 PortNo: flowContext.portNo,
1113 TechProfileId: tpID,
1114 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1115 PbitToGemport: flowContext.pbitToGem,
1116 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001117 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001118 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001119 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301120 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001121 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301122 log.Fields{"direction": direction,
1123 "device-id": f.deviceHandler.device.Id,
1124 "flow": flow,
1125 "intf-id": intfID,
1126 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001127
David K. Bainbridge794735f2020-02-11 21:01:37 -08001128 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301129}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001130
Gamze Abaka7650be62021-02-26 10:50:36 +00001131func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001132 intfID := flowContext.intfID
1133 onuID := flowContext.onuID
1134 uniID := flowContext.uniID
1135 logicalFlow := flowContext.logicalFlow
1136 classifier := flowContext.classifier
1137 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301138
Neha Sharma96b7bf22020-06-15 10:37:32 +00001139 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301140 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301141 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001142 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301143 "action": action,
1144 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001145 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301146 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301147
1148 // Clear the action map
1149 for k := range action {
1150 delete(action, k)
1151 }
1152
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001153 action[TrapToHost] = true
1154 classifier[UDPSrc] = uint32(68)
1155 classifier[UDPDst] = uint32(67)
1156 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301157
yasin saplibddc2d72022-02-08 13:10:17 +00001158 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001159 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001160 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301161 log.Fields{
1162 "device-id": f.deviceHandler.device.Id,
1163 "intf-id": intfID,
1164 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001165 return nil
yasin saplid0566272021-12-21 09:10:30 +00001166 } else if err != nil {
1167 logger.Errorw(ctx, "aborting-addDHCPTrapFlow--flow-may-already-exist",
1168 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1169 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301170 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301171
Neha Sharma96b7bf22020-06-15 10:37:32 +00001172 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301173 log.Fields{
1174 "ul_classifier": classifier,
1175 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001176 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301177 "intf-id": intfID,
1178 "onu-id": onuID,
1179 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301180
David K. Bainbridge794735f2020-02-11 21:01:37 -08001181 classifierProto, err := makeOpenOltClassifierField(classifier)
1182 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301183 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301184 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001185 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001186 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001187 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301188 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301189 }
1190
David K. Bainbridge794735f2020-02-11 21:01:37 -08001191 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001192 OnuId: int32(onuID),
1193 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001194 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001195 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001196 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001197 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001198 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301199 Classifier: classifierProto,
1200 Action: actionProto,
1201 Priority: int32(logicalFlow.Priority),
1202 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001203 PortNo: flowContext.portNo,
1204 TechProfileId: flowContext.tpID,
1205 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1206 PbitToGemport: flowContext.pbitToGem,
1207 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001208 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001209 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001210 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001211 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001212 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301213 log.Fields{
1214 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001215 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301216 "intf-id": intfID,
1217 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301218
David K. Bainbridge794735f2020-02-11 21:01:37 -08001219 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301220}
1221
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001222// addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001223func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1224 delete(flowContext.classifier, VlanVid)
1225 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001226}
1227
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001228// addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001229func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001230 intfID := flowContext.intfID
1231 onuID := flowContext.onuID
1232 uniID := flowContext.uniID
1233 logicalFlow := flowContext.logicalFlow
1234 classifier := flowContext.classifier
1235 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001236
Neha Sharma96b7bf22020-06-15 10:37:32 +00001237 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001238 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301239 return olterrors.NewErrNotFound("nni-interface-id",
1240 log.Fields{
1241 "classifier": classifier,
1242 "action": action,
1243 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001245 }
1246
1247 // Clear the action map
1248 for k := range action {
1249 delete(action, k)
1250 }
1251
1252 action[TrapToHost] = true
1253 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001254
yasin saplibddc2d72022-02-08 13:10:17 +00001255 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001256 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001257 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001258 return nil
yasin saplid0566272021-12-21 09:10:30 +00001259 } else if err != nil {
1260 logger.Errorw(ctx, "aborting-addUpstreamTrapFlow--flow-may-already-exist",
1261 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1262 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00001263 }
1264
Neha Sharma96b7bf22020-06-15 10:37:32 +00001265 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301266 log.Fields{
1267 "ul_classifier": classifier,
1268 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001269 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301270 "device-id": f.deviceHandler.device.Id,
1271 "intf-id": intfID,
1272 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001273
David K. Bainbridge794735f2020-02-11 21:01:37 -08001274 classifierProto, err := makeOpenOltClassifierField(classifier)
1275 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301276 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001277 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001278 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301279 log.Fields{
1280 "classifier": *classifierProto,
1281 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001282 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001283 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301284 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001285 }
1286
David K. Bainbridge794735f2020-02-11 21:01:37 -08001287 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001288 OnuId: int32(onuID),
1289 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001290 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001291 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001292 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001293 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001294 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001295 Classifier: classifierProto,
1296 Action: actionProto,
1297 Priority: int32(logicalFlow.Priority),
1298 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001299 PortNo: flowContext.portNo,
1300 TechProfileId: flowContext.tpID,
1301 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1302 PbitToGemport: flowContext.pbitToGem,
1303 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001304 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001305
David K. Bainbridge794735f2020-02-11 21:01:37 -08001306 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001307 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 -08001308 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001309
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001311}
1312
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001313// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001314func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1315 intfID := flowContext.intfID
1316 onuID := flowContext.onuID
1317 uniID := flowContext.uniID
1318 portNo := flowContext.portNo
1319 allocID := flowContext.allocID
1320 gemPortID := flowContext.gemPortID
1321 logicalFlow := flowContext.logicalFlow
1322 classifier := flowContext.classifier
1323 action := flowContext.action
1324
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001325 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301326 log.Fields{
1327 "intf-id": intfID,
1328 "onu-id": onuID,
1329 "port-no": portNo,
1330 "alloc-id": allocID,
1331 "gemport-id": gemPortID,
1332 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001333 "flow": logicalFlow,
1334 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301335
1336 uplinkClassifier := make(map[string]interface{})
1337 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301338
manikkaraj kbf256be2019-03-25 00:13:48 +05301339 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001340 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001341 uplinkClassifier[PacketTagType] = SingleTag
1342 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001343 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301344 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001345 uplinkAction[TrapToHost] = true
yasin saplibddc2d72022-02-08 13:10:17 +00001346 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001347 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001348 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301349 "device-id": f.deviceHandler.device.Id,
1350 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001351 "intf-id": intfID,
1352 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001353 return nil
yasin saplid0566272021-12-21 09:10:30 +00001354 } else if err != nil {
1355 logger.Errorw(ctx, "aborting-addEthTypeBasedFlow--flow-may-already-exist",
1356 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1357 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301358 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301359 // Add Uplink EthType Flow
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001360 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301361 log.Fields{
1362 "ul_classifier": uplinkClassifier,
1363 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001364 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301365 "device-id": f.deviceHandler.device.Id,
1366 "intf-id": intfID,
1367 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301368
David K. Bainbridge794735f2020-02-11 21:01:37 -08001369 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1370 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301371 return olterrors.NewErrInvalidValue(log.Fields{
1372 "classifier": uplinkClassifier,
1373 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301374 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001375 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301376 log.Fields{
1377 "classifier": *classifierProto,
1378 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001379 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001380 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301381 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301382 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001383 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301384 log.Fields{
1385 "action": *actionProto,
1386 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001387 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301388 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301389 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001390 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301391 "action": action,
1392 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001393 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301394 }
1395
David K. Bainbridge794735f2020-02-11 21:01:37 -08001396 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001397 OnuId: int32(onuID),
1398 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001399 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001400 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001401 AllocId: int32(allocID),
1402 NetworkIntfId: int32(networkIntfID),
1403 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301404 Classifier: classifierProto,
1405 Action: actionProto,
1406 Priority: int32(logicalFlow.Priority),
1407 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001408 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001409 TechProfileId: flowContext.tpID,
1410 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1411 PbitToGemport: flowContext.pbitToGem,
1412 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001413 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001414 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001415 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001416 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001417 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301418 log.Fields{
1419 "device-id": f.deviceHandler.device.Id,
1420 "onu-id": onuID,
1421 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001422 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301423 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001424
David K. Bainbridge794735f2020-02-11 21:01:37 -08001425 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301426}
1427
David K. Bainbridge794735f2020-02-11 21:01:37 -08001428func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001429 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001430
1431 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1432 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1433 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001434 if vlanID != ReservedVlan {
1435 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001436 classifier.OVid = vid
1437 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301438 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07001439 // The classifierInfo[Metadata] is set for the following flows
1440 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
1441 // - Mcast flow that points to a group in the treatment
1442 // This value, when present and valid (not 0 and not 4096), is interpreted as below
1443 // - inner vid for a double tagged packet in the datapath flow
1444 // - outer vid for a single tagged packet in the datapath flow
1445 // - inner vid in the mcast flow that points to a group
David K. Bainbridge82efc492019-09-04 09:57:11 -07001446 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1447 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301448 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1449 // 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 +05301450 // 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 +05301451 // becomes the IVid.
1452 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1453 if vid != ReservedVlan {
1454 classifier.IVid = vid
1455 }
1456 } else {
1457 if vid != ReservedVlan {
1458 classifier.OVid = vid
1459 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001460 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301461 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301462 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001463 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301464 classifier.OPbits = vlanPcp
1465 } else {
1466 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301467 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001468 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1469 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1470 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1471 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001472 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001473 classifier.SrcMac, _ = classifierInfo[EthSrc].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001474 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1475 classifier.PktTagType = pktTagType
1476
1477 switch pktTagType {
1478 case SingleTag:
1479 case DoubleTag:
1480 case Untagged:
1481 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001482 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301483 }
1484 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001485 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301486}
1487
Akash Kankanala041a2122024-10-16 15:49:22 +05301488// nolint: unparam
1489// TODO: Improvise the function & remove the unparam lint, currently it is always returning 'nil' as error.
Gamze Abaka724d0852020-03-18 12:10:24 +00001490func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001491 var actionCmd openoltpb2.ActionCmd
1492 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301493 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001494 if _, ok := actionInfo[PopVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001495 // Pop outer vid
manikkaraj kbf256be2019-03-25 00:13:48 +05301496 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001497 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001498 // Remark inner pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001499 action.Cmd.RemarkInnerPbits = true
1500 action.IPbits = actionInfo[VlanPcp].(uint32)
1501 if _, ok := actionInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001502 // Remark inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001503 action.Cmd.TranslateInnerTag = true
1504 action.IVid = actionInfo[VlanVid].(uint32)
1505 }
1506 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001507 } else if _, ok := actionInfo[PushVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001508 // push outer vid
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001509 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301510 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001511 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001512 // translate outer pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001513 action.OPbits = actionInfo[VlanPcp].(uint32)
1514 action.Cmd.RemarkOuterPbits = true
1515 if _, ok := classifierInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001516 // translate inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001517 action.IVid = classifierInfo[VlanVid].(uint32)
1518 action.Cmd.TranslateInnerTag = true
1519 }
1520 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001521 } else if _, ok := actionInfo[TrapToHost]; ok {
1522 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001523 } else if _, ok := actionInfo[VlanVid]; ok {
1524 // Translate outer vid
1525 action.Cmd.TranslateOuterTag = true
1526 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301527 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301528 // When OLT is transparent to vlans no-action is valid.
1529 /*
1530 else {
1531 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1532 }
1533 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001534 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301535}
1536
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001537// getTPpath return the ETCD path for a given UNI port
yasin saplibddc2d72022-02-08 13:10:17 +00001538func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001539 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301540}
1541
Gamze Abakafee36392019-10-03 11:17:24 +00001542// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001543// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1544// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1545// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1546// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1547// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1548// because it was observed that if the ONU device was deleted too soon after the flows were
1549// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1550// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1551// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001552func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
yasin saplibddc2d72022-02-08 13:10:17 +00001553 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001554 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1555
Gamze Abakafee36392019-10-03 11:17:24 +00001556 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001557 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001558 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001559 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
yasin saplibddc2d72022-02-08 13:10:17 +00001560 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001561 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1562 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1563 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1564 log.Fields{
1565 "tp-id": tpID,
1566 "path": tpPath})
1567 }
1568 switch tpInstance := tpInst.(type) {
1569 case *tp_pb.TechProfileInstance:
1570 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1571 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1572 }
1573 // Force cleanup scheduler/queues -- end
1574
1575 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301576 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001577 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301578 // return err
1579 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001580 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001581 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 +00001582 }
1583 return nil
1584}
1585
1586// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301587func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001588 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001589 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001590 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001591 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301592 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1593 log.Fields{
1594 "tp-id": tpID,
1595 "uni-port-name": uniPortName,
1596 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001597 }
1598 return nil
1599}
1600
David K. Bainbridge794735f2020-02-11 21:01:37 -08001601func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001602 var intfID uint32
1603 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1604 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1605 */
1606 if deviceFlow.AccessIntfId != -1 {
1607 intfID = uint32(deviceFlow.AccessIntfId)
1608 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001609 // We need to log the valid interface ID.
1610 // 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 +00001611 intfID = uint32(deviceFlow.NetworkIntfId)
1612 }
1613
Neha Sharma96b7bf22020-06-15 10:37:32 +00001614 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301615 "flow": *deviceFlow,
1616 "device-id": f.deviceHandler.device.Id,
1617 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001618 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001619
1620 st, _ := status.FromError(err)
1621 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001622 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001623 "err": err,
1624 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301625 "device-id": f.deviceHandler.device.Id,
1626 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001627 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301628 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001629
1630 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001631 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301632 log.Fields{"err": err,
1633 "device-flow": deviceFlow,
1634 "device-id": f.deviceHandler.device.Id,
1635 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001636 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001637 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001638 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301639 log.Fields{
1640 "flow": *deviceFlow,
1641 "device-id": f.deviceHandler.device.Id,
1642 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001643
yasin saplid0566272021-12-21 09:10:30 +00001644 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1645 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1646 return err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001647 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001648 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001649}
1650
Neha Sharma96b7bf22020-06-15 10:37:32 +00001651func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1652 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301653 log.Fields{
1654 "flow": *deviceFlow,
1655 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001656 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001657 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001658 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001659 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301660 log.Fields{
1661 "err": err,
1662 "deviceFlow": deviceFlow,
1663 "device-id": f.deviceHandler.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +05301664 // Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001665 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001666 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001667 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001668 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001669 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001670 "of-flow-id": ofFlowID,
1671 "flow": *deviceFlow,
1672 "device-id": f.deviceHandler.device.Id,
1673 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001674 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301675}
1676
David K. Bainbridge794735f2020-02-11 21:01:37 -08001677func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001678 classifierInfo := make(map[string]interface{})
1679 actionInfo := make(map[string]interface{})
1680
1681 classifierInfo[EthType] = uint32(LldpEthType)
1682 classifierInfo[PacketTagType] = Untagged
1683 actionInfo[TrapToHost] = true
1684
1685 // LLDP flow is installed to trap LLDP packets on the NNI port.
1686 // We manage flow_id resource pool on per PON port basis.
1687 // Since this situation is tricky, as a hack, we pass the NNI port
1688 // index (network_intf_id) as PON port Index for the flow_id resource
1689 // pool. Also, there is no ONU Id available for trapping LLDP packets
1690 // on NNI port, use onu_id as -1 (invalid)
1691 // ****************** CAVEAT *******************
1692 // This logic works if the NNI Port Id falls within the same valid
1693 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1694 // we need to have a re-look at this.
1695 // *********************************************
1696
1697 var onuID = -1
1698 var uniID = -1
1699 var gemPortID = -1
1700
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001701 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001702 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301703 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001704 }
yasin saplibddc2d72022-02-08 13:10:17 +00001705 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001706 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001707 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001708 return nil
yasin saplid0566272021-12-21 09:10:30 +00001709 } else if err != nil {
1710 logger.Errorw(ctx, "aborting-addLLDPFlow--flow-may-already-exist",
1711 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
1712 return err
Humera Kouser94d7a842019-08-25 19:04:32 -04001713 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001714
David K. Bainbridge794735f2020-02-11 21:01:37 -08001715 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1716 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301717 return olterrors.NewErrInvalidValue(
1718 log.Fields{
1719 "classifier": classifierInfo,
1720 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001721 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001722 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301723 log.Fields{
1724 "classifier": *classifierProto,
1725 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001726 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001727 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301728 return olterrors.NewErrInvalidValue(
1729 log.Fields{
1730 "action": actionInfo,
1731 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001732 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001733 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301734 log.Fields{
1735 "action": *actionProto,
1736 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001737
1738 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1739 OnuId: int32(onuID), // OnuId not required
1740 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001741 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001742 FlowType: Downstream,
1743 NetworkIntfId: int32(networkInterfaceID),
1744 GemportId: int32(gemPortID),
1745 Classifier: classifierProto,
1746 Action: actionProto,
1747 Priority: int32(flow.Priority),
1748 Cookie: flow.Cookie,
1749 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001750 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001751 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301752 log.Fields{
1753 "flow": downstreamflow,
1754 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001755 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001756 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301757 log.Fields{
1758 "device-id": f.deviceHandler.device.Id,
1759 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001760 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001761
David K. Bainbridge794735f2020-02-11 21:01:37 -08001762 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301763}
1764
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001765func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1766 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001767}
1768
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001769// getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001770func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001771 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1772 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1773 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001774 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301775 log.Fields{
1776 "intf-id": intfID,
1777 "onu-id": onuID,
1778 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001779 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001780 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301781 return nil, olterrors.NewErrNotFound("onu-child-device",
1782 log.Fields{
1783 "onu-id": onuID,
1784 "intf-id": intfID,
1785 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001786 }
khenaidoo106c61a2021-08-11 18:05:46 -04001787 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 +05301788 // better to ad the device to cache here.
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001789 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1790 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001791 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301792 log.Fields{
1793 "intf-id": intfID,
1794 "onu-id": onuID,
1795 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001796 }
1797
1798 return onuDev.(*OnuDevice), nil
1799}
1800
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001801// getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001802func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1803 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301804 log.Fields{
1805 "pon-port": intfID,
1806 "onu-id": onuID,
1807 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001808 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001809 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001810 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301811 return nil, olterrors.NewErrNotFound("onu",
1812 log.Fields{
1813 "interface-id": parentPortNo,
1814 "onu-id": onuID,
1815 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001816 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301817 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001818 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301819 log.Fields{
1820 "device-id": f.deviceHandler.device.Id,
1821 "child_device_id": onuDevice.Id,
1822 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301823 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301824}
1825
Neha Sharma96b7bf22020-06-15 10:37:32 +00001826func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1827 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301828 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001829 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301830 log.Fields{
1831 "intf-id": intfID,
1832 "onu-id": onuID,
1833 "uni-id": uniID,
1834 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001835 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301836 }
1837
khenaidoodc2116e2021-10-19 17:33:19 -04001838 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001839 DeviceId: onuDev.deviceID,
1840 UniId: uniID,
1841 TpInstancePath: tpPath,
1842 GemPortId: gemPortID,
1843 }
1844 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1845
1846 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301847 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1848 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001849 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1850 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301851 "onu-id": onuDev.deviceID,
1852 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001853 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301854 }
khenaidoo106c61a2021-08-11 18:05:46 -04001855
Neha Sharma96b7bf22020-06-15 10:37:32 +00001856 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301857 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001858 "msg": delGemPortMsg,
1859 "from-adapter": f.deviceHandler.device.Type,
1860 "to-adapter": onuDev.deviceType,
1861 "device-id": f.deviceHandler.device.Id,
1862 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301863 return nil
1864}
1865
Neha Sharma96b7bf22020-06-15 10:37:32 +00001866func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1867 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301868 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001869 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301870 log.Fields{
1871 "intf-id": intfID,
1872 "onu-id": onuID,
1873 "uni-id": uniID,
1874 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001875 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301876 }
1877
khenaidoodc2116e2021-10-19 17:33:19 -04001878 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001879 DeviceId: onuDev.deviceID,
1880 UniId: uniID,
1881 TpInstancePath: tpPath,
1882 AllocId: allocID,
1883 }
1884
Neha Sharma96b7bf22020-06-15 10:37:32 +00001885 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301886 log.Fields{
1887 "msg": *delTcontMsg,
1888 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001889
1890 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301891 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1892 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001893 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1894 "to-adapter": onuDev.adapterEndpoint,
1895 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301896 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001897 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301898 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001899 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301900 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001901 "msg": delTcontMsg,
1902 "device-id": f.deviceHandler.device.Id,
1903 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301904 return nil
1905}
1906
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001907// clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001908// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001909func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Gamze Abaka411ef2f2021-11-22 08:38:08 +00001910 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001911 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001912
Girish Gowdraa482f272021-03-24 23:04:19 -07001913 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
yasin saplibddc2d72022-02-08 13:10:17 +00001914 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001915 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1916 log.Fields{
1917 "tpPath": tpPath,
1918 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001919
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001920 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001921 if err != nil || techprofileInst == nil {
1922 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1923 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1924 if childDevice == nil {
1925 // happens when subscriber un-provision is immediately followed by child device delete
1926 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1927 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1928 return nil
1929 }
Elia Battiston2aaf4342022-02-07 15:16:38 +01001930 // If the tech profile is not found, since we want to delete it, there is no need to throw an error
1931 _ = olterrors.NewErrNotFound("tech-profile-in-kv-store",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001932 log.Fields{
1933 "tp-id": tpID,
Elia Battiston2aaf4342022-02-07 15:16:38 +01001934 "path": tpPath}, err).Log()
1935 return nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001936 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001937
1938 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001939 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001940 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001941 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1942 gemPortID := gemPort.GemportId
Girish Gowdrab4c33302022-03-18 15:07:38 -07001943 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, gemPortID)
1944 if err != nil {
1945 return err
1946 }
1947 used := false
1948 for _, id := range flowIDs {
1949 if flowID != id {
1950 used = true
1951 break
yasin sapli9e4c5092022-02-01 13:52:33 +00001952 }
Girish Gowdrab4c33302022-03-18 15:07:38 -07001953 }
1954 if used {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001955 for i, flowIDinMap := range flowIDs {
1956 if flowIDinMap == flowID {
1957 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
yasin saplibddc2d72022-02-08 13:10:17 +00001958 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, gemPortID, flowIDs); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001959 return err
1960 }
1961 break
1962 }
1963 }
1964 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1965 log.Fields{
1966 "gemport-id": gemPortID,
1967 "usedByFlows": flowIDs,
1968 "currentFlow": flowID,
1969 "device-id": f.deviceHandler.device.Id})
1970 allGemPortsFree = false
1971 }
1972 }
1973 if !allGemPortsFree {
1974 return nil
1975 }
1976 }
1977
1978 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 -08001979
1980 // 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 +00001981 switch techprofileInst := techprofileInst.(type) {
1982 case *tp_pb.TechProfileInstance:
Girish Gowdraf3728b12022-02-02 21:46:51 -08001983 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1984 gemPortID := gemPort.GemportId
yasin saplibddc2d72022-02-08 13:10:17 +00001985 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, uint32(onuID), gemPortID) // ignore error and proceed.
Girish Gowdraf3728b12022-02-02 21:46:51 -08001986
yasin saplibddc2d72022-02-08 13:10:17 +00001987 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, gemPortID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08001988 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
1989 log.Fields{
1990 "err": err,
1991 "intf": intfID,
1992 "onu-id": onuID,
1993 "uni-id": uniID,
1994 "device-id": f.deviceHandler.device.Id,
1995 "gemport-id": gemPortID})
1996 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08001997 }
1998 // Remove queues at OLT in upstream and downstream direction
Akash Kankanala041a2122024-10-16 15:49:22 +05301999 schedQ := schedQueue{tpInst: techprofileInst, direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum}
2000 if err := f.RemoveQueues(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002001 logger.Warn(ctx, err)
2002 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302003 schedQ.direction = tp_pb.Direction_DOWNSTREAM
2004 if err := f.RemoveQueues(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002005 logger.Warn(ctx, err)
2006 }
2007 }
2008
2009 switch techprofileInst := techprofileInst.(type) {
2010 case *tp_pb.TechProfileInstance:
2011 // 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 +05302012 schedQ := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2013 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQ)
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002014 if !allocExists {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002015 // all alloc object references removed, remove upstream scheduler
yasin saplibddc2d72022-02-08 13:10:17 +00002016 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302017 if err := f.RemoveScheduler(ctx, schedQ); err != nil {
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002018 logger.Warn(ctx, err)
2019 }
2020 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002021 // remove alloc id from resource pool by setting the 'freeFromResourcePool' to true
yasin saplibddc2d72022-02-08 13:10:17 +00002022 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, true)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002023 } else {
2024 // just remove meter reference for the upstream direction for the current pon/onu/uni
2025 // 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 +05302026 if err := f.removeMeterReference(ctx, "upstream", schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002027 return err
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002028 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002029 // setting 'freeFromResourcePool' to false in resourceMgr.FreeAllocID will only remove alloc-id data for the given pon/onu/uni
2030 // but still preserve it on the resource pool.
yasin saplibddc2d72022-02-08 13:10:17 +00002031 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, false)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002032 }
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002033
Girish Gowdraf3728b12022-02-02 21:46:51 -08002034 // 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 +05302035 schedQ.direction = tp_pb.Direction_DOWNSTREAM
yasin saplibddc2d72022-02-08 13:10:17 +00002036 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302037 if err := f.RemoveScheduler(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002038 logger.Warn(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002039 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002040 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002041 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002042 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002043 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002044 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302045 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002046 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302047 "onu-id": onuID,
2048 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002049 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002050 "alloc-id": techprofileInst.AllocId,
2051 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002052 }
yasin saplibddc2d72022-02-08 13:10:17 +00002053 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.AllocId, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302054 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
2055 logger.Warn(ctx, err)
2056 }
2057 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2058 logger.Warn(ctx, err)
2059 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002060 default:
2061 logger.Errorw(ctx, "error-unknown-tech",
2062 log.Fields{
2063 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002064 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002065
2066 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
2067 switch techprofileInst := techprofileInst.(type) {
2068 case *tp_pb.TechProfileInstance:
2069 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2070 // Delete the gem port on the ONU.
2071 if sendDeleteGemRequest {
2072 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId, tpPath); err != nil {
2073 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2074 log.Fields{
2075 "err": err,
2076 "intfID": intfID,
2077 "onu-id": onuID,
2078 "uni-id": uniID,
2079 "device-id": f.deviceHandler.device.Id,
2080 "gemport-id": gemPort.GemportId})
2081 }
yasin saplibddc2d72022-02-08 13:10:17 +00002082 f.resourceMgr.FreeGemPortID(ctx, uint32(onuID), uint32(uniID), gemPort.GemportId)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002083 }
2084 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302085 // Delete the tp instance and the techprofileid for onu at the end
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302086 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2087 logger.Warn(ctx, err)
2088 }
2089 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
2090 logger.Warn(ctx, err)
2091 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002092 }
2093
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302094 return nil
2095}
2096
David K. Bainbridge794735f2020-02-11 21:01:37 -08002097// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002098func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002099 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302100 log.Fields{
2101 "flowDirection": flowDirection,
2102 "flow": *flow,
2103 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002104
2105 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002106 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002107 }
2108
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302109 var ethType, ipProto, inPort uint32
2110 for _, field := range flows.GetOfbFields(flow) {
2111 if field.Type == flows.IP_PROTO {
2112 ipProto = field.GetIpProto()
2113 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"ipProto": ipProto})
2114 } else if field.Type == flows.ETH_TYPE {
2115 ethType = field.GetEthType()
2116 logger.Debugw(ctx, "field-type-eth-type", log.Fields{"ethType": ethType})
2117 } else if field.Type == flows.IN_PORT {
2118 inPort = field.GetPort()
2119 logger.Debugw(ctx, "field-type-in-port", log.Fields{"inPort": inPort})
2120 }
2121 }
2122 portType := plt.IntfIDToPortTypeName(inPort)
2123 if (ethType == uint32(LldpEthType) || ipProto == uint32(IPProtoDhcp) || ipProto == uint32(IgmpProto)) &&
2124 (portType == voltha.Port_ETHERNET_NNI) {
2125 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: -1, OnuId: -1, UniId: -1, TechProfileId: 0, FlowType: Downstream}
2126 logger.Debugw(ctx, "nni-trap-flow-to-be-deleted", log.Fields{"flow": flow})
2127 return f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id)
2128 // No more processing needed for trap from nni flows.
2129 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302130
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302131 portNum, Intf, onu, uni, _, _, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302132 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002133 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002134 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302135 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002136 onuID := int32(onu)
2137 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002138 tpID, err := getTpIDFromFlow(ctx, flow)
2139 if err != nil {
2140 return olterrors.NewErrNotFound("tp-id",
2141 log.Fields{
2142 "flow": flow,
2143 "intf-id": Intf,
2144 "onu-id": onuID,
2145 "uni-id": uniID,
2146 "device-id": f.deviceHandler.device.Id}, err)
2147 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302148
Neha Sharma96b7bf22020-06-15 10:37:32 +00002149 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302150 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002151 "flow-id": flow.Id,
2152 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302153 "onu-id": onuID,
2154 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302155
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002156 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2157 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002158 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2159 return err
2160 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002161
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002162 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002163 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2164 "flow-id": flow.Id,
2165 "device-id": f.deviceHandler.device.Id,
2166 "onu-id": onuID,
2167 "intf": Intf,
2168 "err": err,
2169 })
2170 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302171 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002172
Girish Gowdra82c80982021-03-26 16:22:02 -07002173 // 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 +00002174 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, uint32(onuID), uint32(uniID), tpID, false); err != nil {
Girish Gowdra82c80982021-03-26 16:22:02 -07002175 return err
2176 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002177 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002178}
2179
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002180// RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002181func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Matteo Scandolof16389e2021-05-18 00:47:08 +00002182 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302183 var direction string
2184 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002185
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302186 for _, action := range flows.GetActions(flow) {
2187 if action.Type == flows.OUTPUT {
2188 if out := action.GetOutput(); out != nil {
2189 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002190 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302191 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002192 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002193 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002194 }
2195 }
2196 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002197
2198 if flows.HasGroup(flow) {
2199 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002200 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002201 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302202 direction = Upstream
2203 } else {
2204 direction = Downstream
2205 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302206
Girish Gowdracefae192020-03-19 18:14:10 -07002207 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002208 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002209
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002210 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002211}
2212
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002213// isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
Esin Karamanae41e2b2019-12-17 18:13:13 +00002214func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002215 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002216 if ethType, ok := classifierInfo[EthType]; ok {
2217 if ethType.(uint32) == IPv4EthType {
2218 if ipProto, ok := classifierInfo[IPProto]; ok {
2219 if ipProto.(uint32) == IgmpProto {
2220 return true
2221 }
2222 }
2223 }
2224 }
2225 }
2226 return false
2227}
2228
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002229// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002230func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002231 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2232 // The device itself is going to be reset as part of deletion. So nothing to be done.
2233 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2234 return nil
2235 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002236 // Step1 : Fill flowControlBlock
2237 // Step2 : Push the flowControlBlock to ONU channel
2238 // Step3 : Wait on response channel for response
2239 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002240 startTime := time.Now()
2241 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002242 errChan := make(chan error)
2243 flowCb := flowControlBlock{
2244 ctx: ctx,
2245 addFlow: addFlow,
2246 flow: flow,
2247 flowMetadata: flowMetadata,
2248 errChan: &errChan,
2249 }
2250 inPort, outPort := getPorts(flow)
2251 var onuID uint32
2252 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002253 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002254 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002255 if f.flowHandlerRoutineActive[onuID] {
2256 // inPort or outPort is InvalidPort for trap-from-nni flows.
2257 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2258 // Send the flowCb on the ONU flow channel
2259 f.incomingFlows[onuID] <- flowCb
2260 // Wait on the channel for flow handlers return value
2261 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002262 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002263 return err
2264 }
2265 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2266 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002267}
2268
2269// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2270// 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 -07002271func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002272 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002273 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002274 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002275 // block on the channel to receive an incoming flow
2276 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002277 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002278 if flowCb.addFlow {
2279 logger.Info(flowCb.ctx, "adding-flow-start")
2280 startTime := time.Now()
2281 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2282 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2283 // Pass the return value over the return channel
2284 *flowCb.errChan <- err
2285 } else {
2286 logger.Info(flowCb.ctx, "removing-flow-start")
2287 startTime := time.Now()
2288 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2289 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2290 // Pass the return value over the return channel
2291 *flowCb.errChan <- err
2292 }
2293 case <-stopHandler:
2294 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2295 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002296 }
2297 }
2298}
2299
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002300// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002301func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002302 for i, v := range f.stopFlowHandlerRoutine {
2303 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002304 select {
2305 case v <- true:
2306 case <-time.After(time.Second * 5):
2307 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2308 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002309 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002310 f.stopFlowHandlerRoutine[i] = nil
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002311 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002312 f.stopFlowHandlerRoutine = nil
2313
2314 if f.incomingFlows != nil {
2315 for k := range f.incomingFlows {
2316 if f.incomingFlows[k] != nil {
2317 f.incomingFlows[k] = nil
2318 }
2319 }
2320 f.incomingFlows = nil
2321 }
2322
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002323 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002324 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2325}
2326
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002327// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302328// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002329func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002330 classifierInfo := make(map[string]interface{})
2331 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002332 var UsMeterID uint32
2333 var DsMeterID uint32
2334
Neha Sharma96b7bf22020-06-15 10:37:32 +00002335 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302336 log.Fields{
2337 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002338 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002339 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002340
Neha Sharma96b7bf22020-06-15 10:37:32 +00002341 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002342 if err != nil {
2343 // Error logging is already done in the called function
2344 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002345 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302346 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002347
Esin Karamanccb714b2019-11-29 15:02:06 +00002348 if flows.HasGroup(flow) {
2349 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002350 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002351 }
2352
manikkaraj k17652a72019-05-06 09:06:36 -04002353 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002354 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002355 if err != nil {
2356 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002357 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002358 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002359
Neha Sharma96b7bf22020-06-15 10:37:32 +00002360 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302361 log.Fields{
2362 "classifierinfo_inport": classifierInfo[InPort],
2363 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002364 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002365
Humera Kouser94d7a842019-08-25 19:04:32 -04002366 if ethType, ok := classifierInfo[EthType]; ok {
2367 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002368 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002369 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002370 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002371 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002372 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002373 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2374 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2375 }
2376 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002377 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002378 if ipProto, ok := classifierInfo[IPProto]; ok {
2379 if ipProto.(uint32) == IPProtoDhcp {
2380 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302381 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002382 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002383 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002384 }
2385 }
2386 }
2387 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002388 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002389 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002390 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002391 }
A R Karthick1f85b802019-10-11 05:06:05 +00002392
yasin saplibddc2d72022-02-08 13:10:17 +00002393 f.resourceMgr.AddUniPortToOnuInfo(ctx, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002394
Girish Gowdra6071f382021-12-14 12:52:04 +05302395 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002396 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302397 return olterrors.NewErrNotFound("tpid-for-flow",
2398 log.Fields{
2399 "flow": flow,
2400 "intf-id": IntfID,
2401 "onu-id": onuID,
2402 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002403 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002404 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302405 log.Fields{
Girish Gowdra6071f382021-12-14 12:52:04 +05302406 "tp-id": tpID,
Shrey Baid26912972020-04-16 21:02:31 +05302407 "intf-id": intfID,
2408 "onu-id": onuID,
2409 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002410 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002411 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002412 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302413 if err := f.validateMeter(ctx, Upstream, UsMeterID, intfID, onuID, uniID, tpID); err != nil {
2414 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2415 return err
2416 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002417 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002418 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002419 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302420 if err := f.validateMeter(ctx, Downstream, DsMeterID, intfID, onuID, uniID, tpID); err != nil {
2421 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2422 return err
2423 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002424 }
Girish Gowdra6071f382021-12-14 12:52:04 +05302425 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, tpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002426}
Girish Gowdra3d633032019-12-10 16:37:05 +05302427
Esin Karamanccb714b2019-11-29 15:02:06 +00002428// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002429func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302430 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002431 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302432 "classifier-info": classifierInfo,
2433 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002434
Esin Karaman65409d82020-03-18 10:58:18 +00002435 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002436 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002437 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002438 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002439
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002440 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002441
David K. Bainbridge794735f2020-02-11 21:01:37 -08002442 onuID := NoneOnuID
Esin Karamanccb714b2019-11-29 15:02:06 +00002443
yasin saplibddc2d72022-02-08 13:10:17 +00002444 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002445 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002446 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002447 return nil
yasin saplid0566272021-12-21 09:10:30 +00002448 } else if err != nil {
2449 logger.Errorw(ctx, "aborting-handleFlowWithGroup--flow-may-already-exist",
2450 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
2451 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00002452 }
yasin saplid0566272021-12-21 09:10:30 +00002453
David K. Bainbridge794735f2020-02-11 21:01:37 -08002454 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2455 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002456 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002457 }
2458 groupID := actionInfo[GroupID].(uint32)
2459 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002460 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002461 FlowType: Multicast,
2462 NetworkIntfId: int32(networkInterfaceID),
2463 GroupId: groupID,
2464 Classifier: classifierProto,
2465 Priority: int32(flow.Priority),
2466 Cookie: flow.Cookie}
2467
Kent Hagermane6ff1012020-07-14 15:07:53 -04002468 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002469 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002470 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002471 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
Akash Kankanala041a2122024-10-16 15:49:22 +05302472 // get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002473 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302474 // calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002475 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002476 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002477 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302478 // cached group can be removed now
Kent Hagermane6ff1012020-07-14 15:07:53 -04002479 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002480 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002481 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002482 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002483
David K. Bainbridge794735f2020-02-11 21:01:37 -08002484 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002485}
2486
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002487// 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 +00002488func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2489 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002490 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002491 if err != nil {
2492 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2493 }
2494 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002495 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002496
2497 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2498 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002499}
2500
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002501// sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002502func (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 +00002503 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302504 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002505 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302506 log.Fields{
2507 "intf-id": intfID,
2508 "onu-id": onuID,
2509 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002510 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302511 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002512 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002513
yasin saplibddc2d72022-02-08 13:10:17 +00002514 tpPath := f.getTPpath(ctx, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002515 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002516 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002517 UniId: uniID,
2518 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002519 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002520 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002521 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002522
2523 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2524 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302525 return olterrors.NewErrCommunication("send-techprofile-download-request",
2526 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002527 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302528 "to-adapter": onuDev.deviceType,
2529 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002530 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002531 }
nikesh.krishnan81ec7442023-10-31 17:19:34 +05302532 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpid": TpID})
Manikkaraj k884c1242019-04-11 16:26:42 +05302533 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302534}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002535
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002536// GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302537func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002538 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002539
2540 if packetIn.IntfType == "pon" {
2541 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002542 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002543 onuID, uniID := packetIn.OnuId, packetIn.UniId
2544 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 +00002545
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002546 if packetIn.PortNo != 0 {
2547 logicalPortNum = packetIn.PortNo
2548 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002549 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002550 }
2551 // 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 +00002552 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002553 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002554 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002555 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002556
2557 if logger.V(log.DebugLevel) {
2558 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2559 log.Fields{
2560 "logical-port-num": logicalPortNum,
2561 "intf-type": packetIn.IntfType,
2562 "packet": hex.EncodeToString(packetIn.Pkt),
2563 })
2564 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002565 return logicalPortNum, nil
2566}
2567
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002568// GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002569func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002570 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002571
2572 ctag, priority, err := getCTagFromPacket(ctx, packet)
2573 if err != nil {
2574 return 0, err
2575 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302576
Esin Karaman7fb80c22020-07-16 14:23:33 +00002577 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002578 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002579 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002580 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002581 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302582 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002583 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302584 log.Fields{
2585 "pktinkey": pktInkey,
2586 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002587
2588 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002589 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302590 // 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 +00002591 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302592 if err == nil {
2593 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002594 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302595 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002596 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002597 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302598 log.Fields{
2599 "pktinkey": pktInkey,
2600 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302601 return gemPortID, nil
2602 }
2603 }
Shrey Baid26912972020-04-16 21:02:31 +05302604 return uint32(0), olterrors.NewErrNotFound("gem-port",
2605 log.Fields{
2606 "pktinkey": pktInkey,
2607 "gem": gemPortID}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002608}
2609
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002610func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2611 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002612 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002613 classifier[PacketTagType] = DoubleTag
2614 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002615 /* We manage flowId resource pool on per PON port basis.
2616 Since this situation is tricky, as a hack, we pass the NNI port
2617 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002618 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002619 on NNI port, use onu_id as -1 (invalid)
2620 ****************** CAVEAT *******************
2621 This logic works if the NNI Port Id falls within the same valid
2622 range of PON Port Ids. If this doesn't work for some OLT Vendor
2623 we need to have a re-look at this.
2624 *********************************************
2625 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002626 onuID := -1
2627 uniID := -1
2628 gemPortID := -1
2629 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002630 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302631 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302632 return olterrors.NewErrNotFound("nni-intreface-id",
2633 log.Fields{
2634 "classifier": classifier,
2635 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002636 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302637 }
2638
yasin saplibddc2d72022-02-08 13:10:17 +00002639 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002640 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002641 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002642 return nil
yasin saplid0566272021-12-21 09:10:30 +00002643 } else if err != nil {
2644 logger.Errorw(ctx, "aborting-addTrapFlowOnNNI--flow-may-already-exist",
2645 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2646 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002647 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002648
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002649 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2650 log.Fields{
2651 "classifier": classifier,
2652 "action": action,
2653 "flowId": logicalFlow.Id,
2654 "intf-id": networkInterfaceID})
2655
David K. Bainbridge794735f2020-02-11 21:01:37 -08002656 classifierProto, err := makeOpenOltClassifierField(classifier)
2657 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002658 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002659 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002660 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002661 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002662 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002663 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002664 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002665 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002666 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2667 OnuId: int32(onuID), // OnuId not required
2668 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002669 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002670 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002671 AllocId: int32(allocID), // AllocId not used
2672 NetworkIntfId: int32(networkInterfaceID),
2673 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002674 Classifier: classifierProto,
2675 Action: actionProto,
2676 Priority: int32(logicalFlow.Priority),
2677 Cookie: logicalFlow.Cookie,
2678 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002679 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002680 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002681 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002682 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002683 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002684}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002685
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002686// getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
Esin Karamanae41e2b2019-12-17 18:13:13 +00002687func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2688 var packetType string
2689 ovid, ivid := false, false
2690 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2691 vid := vlanID & VlanvIDMask
2692 if vid != ReservedVlan {
2693 ovid = true
2694 }
2695 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07002696
2697 // The classifierInfo[Metadata] is set for the following flows
2698 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
2699 // - Mcast flow that points to a group in the action/treatment
2700 // This value, when present and valid (not 0 and not 4096), is interpreted as below
2701 // - inner vid for a double tagged packet in the datapath flow
2702 // - outer vid for a single tagged packet in the datapath flow
2703 // - inner vid in the mcast flow that points to a group
2704
2705 // It is to be noted though that for DT FTTH downstream table0 flow, the classifierInfo[Metadata] is absent.
2706 // And consequently the ivid is not set to true. This will result in packetType being set to singleTag which is not true
2707 // Interestingly enough, this function `getPacketTypeFromClassifiers` is called only by Mcast flow handlers and
2708 // 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 +00002709 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2710 vid := uint32(metadata)
2711 if vid != ReservedVlan {
2712 ivid = true
2713 }
2714 }
2715 if ovid && ivid {
2716 packetType = DoubleTag
2717 } else if !ovid && !ivid {
2718 packetType = Untagged
2719 } else {
2720 packetType = SingleTag
2721 }
2722 return packetType
2723}
2724
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002725// addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002726func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002727 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002728 action := make(map[string]interface{})
2729 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2730 action[TrapToHost] = true
2731 /* We manage flowId resource pool on per PON port basis.
2732 Since this situation is tricky, as a hack, we pass the NNI port
2733 index (network_intf_id) as PON port Index for the flowId resource
2734 pool. Also, there is no ONU Id available for trapping packets
2735 on NNI port, use onu_id as -1 (invalid)
2736 ****************** CAVEAT *******************
2737 This logic works if the NNI Port Id falls within the same valid
2738 range of PON Port Ids. If this doesn't work for some OLT Vendor
2739 we need to have a re-look at this.
2740 *********************************************
2741 */
2742 onuID := -1
2743 uniID := -1
2744 gemPortID := -1
2745 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002746 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002747 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302748 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002749 "classifier": classifier,
2750 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002751 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002752 }
yasin saplibddc2d72022-02-08 13:10:17 +00002753 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002754 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002755 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002756 return nil
yasin saplid0566272021-12-21 09:10:30 +00002757 } else if err != nil {
2758 logger.Errorw(ctx, "aborting-addIgmpTrapFlowOnNNI--flow-may-already-exist",
2759 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2760 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002761 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002762
David K. Bainbridge794735f2020-02-11 21:01:37 -08002763 classifierProto, err := makeOpenOltClassifierField(classifier)
2764 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002765 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002766 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002767 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002768 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002769 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002770 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002771 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002772 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002773 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2774 OnuId: int32(onuID), // OnuId not required
2775 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002776 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002777 FlowType: Downstream,
2778 AllocId: int32(allocID), // AllocId not used
2779 NetworkIntfId: int32(networkInterfaceID),
2780 GemportId: int32(gemPortID), // GemportId not used
2781 Classifier: classifierProto,
2782 Action: actionProto,
2783 Priority: int32(logicalFlow.Priority),
2784 Cookie: logicalFlow.Cookie,
2785 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002786 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002787 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002788 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002789 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002790
David K. Bainbridge794735f2020-02-11 21:01:37 -08002791 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002792}
2793
salmansiddiqui7ac62132019-08-22 03:58:50 +00002794func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2795 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302796 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002797 }
2798 if Dir == tp_pb.Direction_UPSTREAM {
2799 return "upstream", nil
2800 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2801 return "downstream", nil
2802 }
2803 return "", nil
2804}
2805
Kent Hagermane6ff1012020-07-14 15:07:53 -04002806// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302807func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002808 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002809 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002810 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002811 intfID := args[IntfID]
2812 onuID := args[OnuID]
2813 uniID := args[UniID]
2814 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002815 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002816 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002817 gemToAes := make(map[uint32]bool)
2818
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002819 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002820 var direction = tp_pb.Direction_UPSTREAM
2821 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002822 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002823 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002824 attributes = TpInst.UpstreamGemPortAttributeList
2825 } else {
2826 attributes = TpInst.DownstreamGemPortAttributeList
2827 direction = tp_pb.Direction_DOWNSTREAM
2828 }
2829 default:
2830 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002831 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002832 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002833
2834 if len(gemPorts) == 1 {
2835 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002836 gemPortID = gemPorts[0]
2837 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002838 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2839 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002840 pBitMap := attributes[idx].PbitMap
2841 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2842 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2843 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002844 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002845 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2846 if pbitSet == pbit1 {
2847 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2848 pbitToGem[pcp] = gemID
2849 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002850 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002851 }
2852 }
2853 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002854 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2855 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2856 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002857 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002858 }
2859
Akash Kankanala041a2122024-10-16 15:49:22 +05302860 flowContext := &flowContext{classifierInfo, actionInfo, flow, pbitToGem, gemToAes, intfID, onuID, uniID, portNo, allocID, gemPortID, tpID}
Gamze Abaka7650be62021-02-26 10:50:36 +00002861
salmansiddiqui7ac62132019-08-22 03:58:50 +00002862 if ipProto, ok := classifierInfo[IPProto]; ok {
2863 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002864 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002865 "tp-id": tpID,
2866 "alloc-id": allocID,
2867 "intf-id": intfID,
2868 "onu-id": onuID,
2869 "uni-id": uniID,
2870 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302871 // Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002872 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002873 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002874 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})
2875 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002876 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002877 }
Girish Gowdra32625212020-04-29 11:26:35 -07002878 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002879 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302880 log.Fields{
2881 "intf-id": intfID,
2882 "onu-id": onuID,
2883 "uni-id": uniID,
2884 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002885 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002886 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002887 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})
2888 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002889 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002890 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002891 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002892 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002893 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002894 }
2895 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002896 if ethType.(uint32) == EapEthType {
2897 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002898 "intf-id": intfID,
2899 "onu-id": onuID,
2900 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002901 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002902 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002903 var vlanID uint32
2904 if val, ok := classifierInfo[VlanVid]; ok {
2905 vlanID = (val.(uint32)) & VlanvIDMask
2906 } else {
2907 vlanID = DefaultMgmtVlan
2908 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002909 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002910 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002911 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})
2912 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002913 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002914 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002915 } else if ethType.(uint32) == PPPoEDEthType {
2916 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2917 "tp-id": tpID,
2918 "alloc-id": allocID,
2919 "intf-id": intfID,
2920 "onu-id": onuID,
2921 "uni-id": uniID,
2922 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302923 // Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002924 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002925 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002926 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})
2927 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002928 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002929 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002930 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002931 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002932 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002933 "intf-id": intfID,
2934 "onu-id": onuID,
2935 "uni-id": uniID,
2936 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302937 // Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002938 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002939 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002940 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})
2941 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002942 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002943 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002944 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002945 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002946 "intf-id": intfID,
2947 "onu-id": onuID,
2948 "uni-id": uniID,
2949 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302950 // Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002951 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002952 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002953 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})
2954 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002955 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002956 }
2957 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002958 return olterrors.NewErrInvalidValue(log.Fields{
2959 "intf-id": intfID,
2960 "onu-id": onuID,
2961 "uni-id": uniID,
2962 "classifier": classifierInfo,
2963 "action": actionInfo,
2964 "flow": flow},
2965 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002966 }
2967 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002968 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002969 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002970 logger.Warn(ctx, err)
2971 }
2972 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002973 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00002974}
2975
Gamze Abakacb0e6772021-06-10 08:32:12 +00002976func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002977 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2978 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2979 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 +05302980 for i := 0; i < len(tpInstances); i++ {
2981 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00002982 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002983 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002984 logger.Debugw(ctx, "alloc-is-in-use-on-another-uni",
Gamze Abakacb0e6772021-06-10 08:32:12 +00002985 log.Fields{
2986 "device-id": f.deviceHandler.device.Id,
2987 "intfID": sq.intfID,
2988 "onuID": sq.onuID,
2989 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002990 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00002991 })
2992 return true
Girish Gowdra54934262019-11-13 14:19:55 +05302993 }
2994 }
2995 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002996 return false
Gamze Abakafee36392019-10-03 11:17:24 +00002997}
2998
Neha Sharma96b7bf22020-06-15 10:37:32 +00002999func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003000 for _, field := range flows.GetOfbFields(flow) {
3001 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003002 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003003 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003004 } else if field.Type == flows.ETH_DST {
3005 classifierInfo[EthDst] = field.GetEthDst()
Girish Gowdraffa52e52022-02-16 15:48:10 -08003006 logger.Debug(ctx, "field-type-eth-dst", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
3007 } else if field.Type == flows.ETH_SRC {
3008 classifierInfo[EthSrc] = field.GetEthSrc()
3009 logger.Debug(ctx, "field-type-eth-src", log.Fields{"classifierInfo[ETH_SRC]": classifierInfo[EthSrc].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003010 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003011 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003012 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003013 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003014 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003015 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003016 } else if field.Type == flows.VLAN_VID {
Andrea Campanellafaa42152021-10-28 11:50:56 +05303017 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3018 if field.GetVlanVid() != ReservedVlan {
3019 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3020 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3021 }
Scott Baker355d1742019-10-24 10:57:52 -07003022 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003023 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003024 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003025 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003026 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003027 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003028 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003029 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003030 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003031 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003032 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003033 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003034 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003035 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003036 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003037 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003038 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003039 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003040 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003041 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003042 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003043 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003044 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003045 return
3046 }
3047 }
3048}
3049
Neha Sharma96b7bf22020-06-15 10:37:32 +00003050func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003051 for _, action := range flows.GetActions(flow) {
3052 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003053 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003054 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003055 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003056 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003057 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003058 }
Scott Baker355d1742019-10-24 10:57:52 -07003059 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003060 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003061 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003062 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003063 if out := action.GetPush(); out != nil {
3064 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003065 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003066 } else {
3067 actionInfo[PushVlan] = true
3068 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003069 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303070 log.Fields{
3071 "push-tpid": actionInfo[TPID].(uint32),
3072 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003073 }
3074 }
Scott Baker355d1742019-10-24 10:57:52 -07003075 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003076 if out := action.GetSetField(); out != nil {
3077 if field := out.GetField(); field != nil {
3078 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003079 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003080 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003081 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3082 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003083 }
3084 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003085 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003086 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003087 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003088 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003089 }
3090 }
3091 return nil
3092}
3093
Neha Sharma96b7bf22020-06-15 10:37:32 +00003094func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003095 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003096 fieldtype := ofbField.GetType()
3097 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003098 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3099 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003100 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003101 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003102 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003103 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003104 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3105 pcp := ofbField.GetVlanPcp()
3106 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003107 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003108 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003109 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003110 }
3111 }
3112}
3113
Neha Sharma96b7bf22020-06-15 10:37:32 +00003114func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003115 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003116 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003117 } else {
3118 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003119 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003120 }
3121}
3122
Neha Sharma96b7bf22020-06-15 10:37:32 +00003123func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003124 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003125 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003126 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003127 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003128 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003129 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003130 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303131 log.Fields{
3132 "newinport": classifierInfo[InPort].(uint32),
3133 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003134 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303135 return olterrors.NewErrNotFound("child-in-port",
3136 log.Fields{
3137 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3138 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003139 }
3140 }
3141 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003142 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003143 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003144 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003145 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003146 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003147 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303148 log.Fields{
3149 "newoutport": actionInfo[Output].(uint32),
3150 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003151 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303152 return olterrors.NewErrNotFound("out-port",
3153 log.Fields{
3154 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3155 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003156 }
3157 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003158 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003159 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003160 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003161 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303162 log.Fields{
3163 "newinport": actionInfo[Output].(uint32),
3164 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003165 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303166 return olterrors.NewErrNotFound("nni-port",
3167 log.Fields{
3168 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3169 "in-port": classifierInfo[InPort].(uint32),
3170 "out-port": actionInfo[Output].(uint32),
3171 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003172 }
3173 }
3174 }
3175 return nil
3176}
Gamze Abakafee36392019-10-03 11:17:24 +00003177
Neha Sharma96b7bf22020-06-15 10:37:32 +00003178func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003179 /* Metadata 8 bytes:
3180 Most Significant 2 Bytes = Inner VLAN
3181 Next 2 Bytes = Tech Profile ID(TPID)
3182 Least Significant 4 Bytes = Port ID
3183 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3184 subscriber related flows.
3185 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003186 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003187 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003188 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003189 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003190 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003191 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003192}
3193
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003194func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003195 for _, sliceElement := range slice {
3196 if sliceElement == item {
3197 return slice
3198 }
3199 }
3200 return append(slice, item)
3201}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303202
yasin saplie87d4bd2021-12-06 09:04:03 +00003203func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3204 for _, sliceElement := range slice {
3205 if sliceElement == item {
3206 return slice
3207 }
3208 }
3209 return append(slice, item)
3210}
3211
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303212// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003213func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003214 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303215 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003216 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003217 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003218 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003219 log.Fields{
3220 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003221 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003222 return uint32(0), err
3223 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003224 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303225 return intfID, nil
3226 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003227 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003228 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003229 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003230 log.Fields{
3231 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003232 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003233 return uint32(0), err
3234 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003235 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303236 return intfID, nil
3237 }
3238 return uint32(0), nil
3239}
3240
3241// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003242func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3243 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3244 if err != nil {
3245 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3246 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3247 return
3248 }
3249 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003250
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003251 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003252 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003253 f.packetInGemPortLock.RUnlock()
3254
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303255 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003256 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003257 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 +05303258 log.Fields{
3259 "pktinkey": pktInkey,
3260 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003261 return
3262 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303263 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003264 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003265 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003266 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003267
npujarec5762e2020-01-01 14:08:48 +05303268 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003269 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 +05303270 log.Fields{
3271 "pktinkey": pktInkey,
3272 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303273}
3274
Joey Armstrong3f0e2422023-07-05 18:25:41 -04003275// getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003276func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3277 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003278 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003279 return 0, 0, errors.New("invalid packet length")
3280 }
3281 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3282 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3283
3284 var index int8
3285 if outerEthType == 0x8100 {
3286 if innerEthType == 0x8100 {
3287 // q-in-q 802.1ad or 802.1q double tagged packet.
3288 // get the inner vlanId
3289 index = 18
3290 } else {
3291 index = 14
3292 }
3293 priority := (packet[index] >> 5) & 0x7
Akash Kankanala041a2122024-10-16 15:49:22 +05303294 // 13 bits composes vlanId value
Esin Karaman7fb80c22020-07-16 14:23:33 +00003295 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3296 return vlan, priority, nil
3297 }
3298 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3299 return 0, 0, nil
3300}
3301
Joey Armstrong3f0e2422023-07-05 18:25:41 -04003302// clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
Girish Gowdra9602eb42020-09-09 15:50:39 -07003303// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003304func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003305 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003306 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3307 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003308 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003309 "flow-id": flow.Id,
3310 "device-id": f.deviceHandler.device.Id})
3311 // Remove from device
3312 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3313 // DKB
3314 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3315 log.Fields{
3316 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003317 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003318 return err
3319 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003320
3321 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003322}
3323
khenaidoodc2116e2021-10-19 17:33:19 -04003324func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003325 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003326 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003327 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003328 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003329 }
3330
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003331 switch tpInst := tpInst.(type) {
3332 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003333 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003334 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003335 DeviceId: onuDeviceID,
3336 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003337 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003338 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003339 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003340 case *tp_pb.EponTechProfileInstance:
3341 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003342 DeviceId: onuDeviceID,
3343 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003344 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003345 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003346 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003347 default:
3348 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003349 }
khenaidoodc2116e2021-10-19 17:33:19 -04003350 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003351 DeviceId: onuDeviceID,
3352 UniId: uniID,
3353 TpInstancePath: tpPath,
3354 TechTpInstance: nil,
3355 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003356}
3357
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003358// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3359func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003360 intfID := sq.intfID
3361 onuID := sq.onuID
3362 uniID := sq.uniID
3363 tpID := sq.tpID
3364
3365 var reverseDirection string
3366 if sq.direction == tp_pb.Direction_UPSTREAM {
3367 reverseDirection = "downstream"
3368 } else {
3369 reverseDirection = "upstream"
3370 }
3371
3372 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
yasin saplibddc2d72022-02-08 13:10:17 +00003373 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, onuID, uniID, tpID); KvStoreMeter != nil {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003374 return
3375 }
3376
3377 // revert-delete tech-profile instance and delete tech profile id for onu
3378 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})
3379 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3380 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
yasin saplibddc2d72022-02-08 13:10:17 +00003381 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, onuID, uniID, tpID)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003382
3383 // free gem/alloc
3384 switch techprofileInst := sq.tpInst.(type) {
3385 case *tp_pb.TechProfileInstance:
3386 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
yasin saplibddc2d72022-02-08 13:10:17 +00003387 f.resourceMgr.FreeGemPortID(ctx, onuID, uniID, gem.GemportId)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003388 }
yasin saplibddc2d72022-02-08 13:10:17 +00003389 f.resourceMgr.FreeAllocID(ctx, onuID, uniID, techprofileInst.UsScheduler.AllocId, true)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003390 }
3391}
3392
3393// revertSchduler is called when CreateQueues request fails
3394func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3395 // revert scheduler
3396 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})
3397 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
3398 IntfId: sq.intfID, OnuId: sq.onuID,
3399 UniId: sq.uniID, PortNo: sq.uniPort,
3400 TrafficScheds: TrafficSched})
3401}
Girish Gowdra6071f382021-12-14 12:52:04 +05303402
3403// validateMeter validates if there is a meter mismatch for the given direction. It also clears the stale meter if the reference count is zero
3404func (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 +00003405 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, onuID, uniID, tpID)
Girish Gowdra6071f382021-12-14 12:52:04 +05303406 if err != nil {
3407 return olterrors.NewErrNotFound("meter",
3408 log.Fields{"intf-id": intfID,
3409 "onu-id": onuID,
3410 "uni-id": uniID,
3411 "device-id": f.deviceHandler.device.Id}, err)
3412 }
3413
3414 if meterInfo != nil {
3415 // If RefCnt become 0 clear the meter information from the DB.
3416 if meterInfo.MeterID != meterID && meterInfo.RefCnt == 0 {
yasin saplibddc2d72022-02-08 13:10:17 +00003417 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, onuID, uniID, tpID); err != nil {
Girish Gowdra6071f382021-12-14 12:52:04 +05303418 return err
3419 }
3420 } else if meterInfo.MeterID != meterID {
3421 logger.Errorw(ctx, "meter-mismatch-for-direction",
3422 log.Fields{"direction": direction,
3423 "kv-store-meter-id": meterInfo.MeterID,
3424 "meter-id-in-flow": meterID,
3425 "device-id": f.deviceHandler.device.Id})
3426 return olterrors.NewErrInvalidValue(log.Fields{
3427 "unsupported": "meter-id",
3428 "kv-store-meter-id": meterInfo.MeterID,
3429 "meter-id-in-flow": meterID,
3430 "device-id": f.deviceHandler.device.Id}, nil)
3431 }
3432 }
3433 return nil
3434}
Girish Gowdraf3728b12022-02-02 21:46:51 -08003435
3436func (f *OpenOltFlowMgr) removeMeterReference(ctx context.Context, direction string, sq schedQueue) error {
3437 /* After we successfully remove the scheduler configuration on the OLT device,
3438 * delete the meter id on the KV store.
3439 */
yasin saplibddc2d72022-02-08 13:10:17 +00003440 err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Girish Gowdraf3728b12022-02-02 21:46:51 -08003441 if err != nil {
3442 return olterrors.NewErrAdapter("unable-to-remove-meter",
3443 log.Fields{
3444 "onu": sq.onuID,
3445 "device-id": f.deviceHandler.device.Id,
3446 "intf-id": sq.intfID,
3447 "onu-id": sq.onuID,
3448 "uni-id": sq.uniID,
3449 "uni-port": sq.uniPort}, err)
3450 }
3451 logger.Debugw(ctx, "removed-meter-from-KV-store-successfully",
3452 log.Fields{
3453 "dir": direction,
3454 "device-id": f.deviceHandler.device.Id,
3455 "intf-id": sq.intfID,
3456 "onu-id": sq.onuID,
3457 "uni-id": sq.uniID,
3458 "uni-port": sq.uniPort})
3459 return err
3460}