blob: 818b1671d0cc769be008661145442ec1b57c1a7b [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
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
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package 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 (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070050 //IPProtoDhcp flow category
51 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Girish Gowdraa09aeab2020-09-14 16:30:52 -070053 //IgmpProto proto value
54 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070055
56 //EapEthType eapethtype value
57 EapEthType = 0x888e
58 //LldpEthType lldp ethtype value
59 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000060 //IPv4EthType IPv4 ethernet type value
61 IPv4EthType = 0x800
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030062 //PPPoEDEthType PPPoE discovery ethernet type value
63 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070064
Andrea Campanella7acc0b92020-02-14 09:20:49 +010065 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
66 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040067
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068 //DefaultMgmtVlan default vlan value
69 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
David K. Bainbridge82efc492019-09-04 09:57:11 -070073 //Upstream constant
74 Upstream = "upstream"
75 //Downstream constant
76 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000077 //Multicast constant
78 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070079 //PacketTagType constant
80 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070081 //Untagged constant
82 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070083 //SingleTag constant
84 SingleTag = "single_tag"
85 //DoubleTag constant
86 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053087
88 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089
90 //EthType constant
91 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000092 //EthDst constant
93 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070094 //TPID constant
95 TPID = "tpid"
96 //IPProto constant
97 IPProto = "ip_proto"
98 //InPort constant
99 InPort = "in_port"
100 //VlanVid constant
101 VlanVid = "vlan_vid"
102 //VlanPcp constant
103 VlanPcp = "vlan_pcp"
104
105 //UDPDst constant
106 UDPDst = "udp_dst"
107 //UDPSrc constant
108 UDPSrc = "udp_src"
109 //Ipv4Dst constant
110 Ipv4Dst = "ipv4_dst"
111 //Ipv4Src constant
112 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700113 //Metadata constant
114 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700115 //TunnelID constant
116 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700117 //Output constant
118 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000119 //GroupID constant
120 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700121 // Actions
122
123 //PopVlan constant
124 PopVlan = "pop_vlan"
125 //PushVlan constant
126 PushVlan = "push_vlan"
127 //TrapToHost constant
128 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400129 //MaxMeterBand constant
130 MaxMeterBand = 2
131 //VlanPCPMask contant
132 VlanPCPMask = 0xFF
133 //VlanvIDMask constant
134 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000135 //IntfID constant
136 IntfID = "intfId"
137 //OnuID constant
138 OnuID = "onuId"
139 //UniID constant
140 UniID = "uniId"
141 //PortNo constant
142 PortNo = "portNo"
143 //AllocID constant
144 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000145 //GemID constant
146 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000147
148 //NoneOnuID constant
149 NoneOnuID = -1
150 //NoneUniID constant
151 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700152
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700153 // Max number of flows that can be queued per ONU
154 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530155
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700156 bitMapPrefix = "0b"
157 pbit1 = '1'
158)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400159
Gamze Abakafee36392019-10-03 11:17:24 +0000160type schedQueue struct {
161 direction tp_pb.Direction
162 intfID uint32
163 onuID uint32
164 uniID uint32
165 tpID uint32
166 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700167 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000168 meterID uint32
khenaidoodc2116e2021-10-19 17:33:19 -0400169 flowMetadata *ofp.FlowMetadata
Gamze Abakafee36392019-10-03 11:17:24 +0000170}
171
Gamze Abaka7650be62021-02-26 10:50:36 +0000172type flowContext struct {
173 intfID uint32
174 onuID uint32
175 uniID uint32
176 portNo uint32
177 classifier map[string]interface{}
178 action map[string]interface{}
179 logicalFlow *ofp.OfpFlowStats
180 allocID uint32
181 gemPortID uint32
182 tpID uint32
183 pbitToGem map[uint32]uint32
184 gemToAes map[uint32]bool
185}
186
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700187// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
188// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
189// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
190// flow and processes it serially
191type flowControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400192 ctx context.Context // Flow handler context
193 addFlow bool // if true flow to be added, else removed
194 flow *ofp.OfpFlowStats // Flow message
195 flowMetadata *ofp.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
196 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000197}
198
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700199//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530200type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700201 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700202 techprofile tp.TechProfileIf
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700203 deviceHandler *DeviceHandler
204 grpMgr *OpenOltGroupMgr
205 resourceMgr *rsrcMgr.OpenOltResourceMgr
206
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700207 gemToFlowIDs map[uint32][]uint64 // gem port id to flow ids
208 gemToFlowIDsKey sync.RWMutex // lock to be used to access the gemToFlowIDs map
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700209
210 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
211 packetInGemPortLock sync.RWMutex
212
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700213 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700214 onuGemInfoMap map[uint32]*rsrcMgr.OnuGemInfo //onu, gem and uni info local cache -> map of onuID to OnuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700215 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700216 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700217
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700218 flowIDToGems map[uint64][]uint32
219 flowIDToGemsLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700220
221 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
222 // 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 -0700223 incomingFlows []chan flowControlBlock
224 stopFlowHandlerRoutine []chan bool
225 flowHandlerRoutineActive []bool
manikkaraj kbf256be2019-03-25 00:13:48 +0530226}
227
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700228//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700229func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000230 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530231 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530232 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530233
manikkaraj kbf256be2019-03-25 00:13:48 +0530234 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700235 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700236 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530237 flowMgr.resourceMgr = rMgr
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700238 if err = flowMgr.populateTechProfileForCurrentPonPort(ctx); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700239 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530240 return nil
241 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700242 flowMgr.gemToFlowIDs = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530243 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700244 flowMgr.flowIDToGems = make(map[uint64][]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 flowMgr.onuGemInfoMap = make(map[uint32]*rsrcMgr.OnuGemInfo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530261 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700262 onuIDStart := flowMgr.deviceHandler.deviceInfo.OnuIdStart
263 onuIDEnd := flowMgr.deviceHandler.deviceInfo.OnuIdEnd
264 for onuID := onuIDStart; onuID <= onuIDEnd; onuID++ {
265 // check for a valid serial number in onuGem as GetOnuGemInfo can return nil error in case of nothing found in the path.
Gamze Abaka6f345c12021-09-08 01:14:33 +0000266 onugem, err := rMgr.GetOnuGemInfo(ctx, ponPortIdx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700267 if err == nil && onugem != nil && onugem.SerialNumber != "" {
268 flowMgr.onuGemInfoMap[onuID] = onugem
269 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530270 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700271
272 //Load flowID list per gem map And gemIDs per flow per interface from the kvstore.
273 flowMgr.loadFlowIDsForGemAndGemIDsForFlow(ctx)
274
Esin Karamanccb714b2019-11-29 15:02:06 +0000275 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700276 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000277 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530278 return &flowMgr
279}
280
Kent Hagermane6ff1012020-07-14 15:07:53 -0400281func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700282 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
283 // Flow is not replicated in this case, we need to register the flow for a single gem-port
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700284 return f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700285 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
286 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
287 for _, gemPort := range deviceFlow.PbitToGemport {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700288 if err := f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700289 return err
290 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700291 }
Gamze Abakafee36392019-10-03 11:17:24 +0000292 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700293 return nil
294}
295
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700296func (f *OpenOltFlowMgr) registerFlowIDForGemAndGemIDForFlow(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
297 // update gem->flows map
298 f.gemToFlowIDsKey.Lock()
299 flowIDList, ok := f.gemToFlowIDs[gemPortID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700300 if !ok {
301 flowIDList = []uint64{flowFromCore.Id}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700302 } else {
303 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700304 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700305 f.gemToFlowIDs[gemPortID] = flowIDList
306 f.gemToFlowIDsKey.Unlock()
307
308 // update flow->gems map
309 f.flowIDToGemsLock.Lock()
310 if _, ok := f.flowIDToGems[flowFromCore.Id]; !ok {
311 f.flowIDToGems[flowFromCore.Id] = []uint32{gemPortID}
312 } else {
313 f.flowIDToGems[flowFromCore.Id] = appendUnique32bit(f.flowIDToGems[flowFromCore.Id], gemPortID)
314 }
315 f.flowIDToGemsLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700316
317 // update the flowids for a gem to the KVstore
318 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400319}
320
Girish Gowdra9602eb42020-09-09 15:50:39 -0700321func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000322 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
khenaidoodc2116e2021-10-19 17:33:19 -0400323 UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000324 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530325 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700326 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530327
Neha Sharma96b7bf22020-06-15 10:37:32 +0000328 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530329 "device-id": f.deviceHandler.device.Id,
330 "intf-id": intfID,
331 "onu-id": onuID,
332 "uni-id": uniID,
333 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700334 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530335 "action": actionInfo,
336 "usmeter-iD": UsMeterID,
337 "dsmeter-iD": DsMeterID,
338 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400339 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
340 // is because the flow is an NNI flow and there would be no onu resources associated with it
341 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400342 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200343 cause := "no-onu-id-for-flow"
344 fields := log.Fields{
345 "onu": onuID,
346 "port-no": portNo,
347 "classifer": classifierInfo,
348 "action": actionInfo,
349 "device-id": f.deviceHandler.device.Id}
350 logger.Errorw(ctx, cause, fields)
351 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530352 }
353
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700354 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000355 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530356 "uni": uni,
357 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530358
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700359 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
360 "device-id": f.deviceHandler.device.Id,
361 "intf-id": intfID,
362 "onu-id": onuID,
363 "uni-id": uniID,
364 "port-no": portNo,
365 "classifier": classifierInfo,
366 "action": actionInfo,
367 "usmeter-id": UsMeterID,
368 "dsmeter-id": DsMeterID,
369 "tp-id": TpID})
370 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
371 if allocID == 0 || gemPorts == nil || TpInst == nil {
372 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
373 return olterrors.NewErrNotFound(
374 "alloc-id-gem-ports-tp-unavailable",
375 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400376 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700377 args := make(map[string]uint32)
378 args[IntfID] = intfID
379 args[OnuID] = onuID
380 args[UniID] = uniID
381 args[PortNo] = portNo
382 args[AllocID] = allocID
383
384 /* Flows can be added specific to gemport if p-bits are received.
385 * If no pbit mentioned then adding flows for all gemports
386 */
Gamze Abaka6d0a64f2021-11-18 08:08:33 +0000387 return f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530388}
389
salmansiddiqui7ac62132019-08-22 03:58:50 +0000390// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Girish Gowdraf3728b12022-02-02 21:46:51 -0800391// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530392func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400393
Girish Gowdraf3728b12022-02-02 21:46:51 -0800394 logger.Infow(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530395 log.Fields{"dir": sq.direction,
396 "intf-id": sq.intfID,
397 "onu-id": sq.onuID,
398 "uni-id": sq.uniID,
399 "tp-id": sq.tpID,
400 "meter-id": sq.meterID,
401 "tp-inst": sq.tpInst,
402 "flowmetadata": sq.flowMetadata,
403 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400404
Girish Gowdra6071f382021-12-14 12:52:04 +0530405 direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000406 if err != nil {
407 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400408 }
409
Girish Gowdraf3728b12022-02-02 21:46:51 -0800410 var TrafficShaping *tp_pb.TrafficShapingInfo
411 if sq.flowMetadata == nil || len(sq.flowMetadata.Meters) != 1 {
412 return olterrors.NewErrInvalidValue(log.Fields{
413 "reason": "invalid-meter-config",
414 "meter-id": sq.meterID,
415 "device-id": f.deviceHandler.device.Id}, nil)
416 }
417
418 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
419 return olterrors.NewErrInvalidValue(log.Fields{
420 "reason": "invalid-meter-config",
421 "meter-id": sq.meterID,
422 "device-id": f.deviceHandler.device.Id}, nil)
423 }
424
425 var SchedCfg *tp_pb.SchedulerConfig
426 if sq.direction == tp_pb.Direction_UPSTREAM {
427 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
428 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
429 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
430 }
431 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
432 TrafficSched[0].TechProfileId = sq.tpID
433
Manikkaraj kb1d51442019-07-23 10:41:02 -0400434 /* Lets make a simple assumption that if the meter-id is present on the KV store,
435 * then the scheduler and queues configuration is applied on the OLT device
436 * in the given direction.
437 */
Girish Gowdra6071f382021-12-14 12:52:04 +0530438 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400439 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530440 return olterrors.NewErrNotFound("meter",
441 log.Fields{"intf-id": sq.intfID,
442 "onu-id": sq.onuID,
443 "uni-id": sq.uniID,
444 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400445 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000446
Girish Gowdraf3728b12022-02-02 21:46:51 -0800447 // update reference count and return if the meter was already installed before
Girish Gowdra6071f382021-12-14 12:52:04 +0530448 if meterInfo != nil && meterInfo.MeterID == sq.meterID {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800449 logger.Infow(ctx, "scheduler-already-created-for-direction",
Girish Gowdra6071f382021-12-14 12:52:04 +0530450 log.Fields{"device-id": f.deviceHandler.device.Id, "direction": direction, "meter-id": sq.meterID})
Girish Gowdraf3728b12022-02-02 21:46:51 -0800451 if err = f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
452 return err
453 }
454
455 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); allocExists {
456 // Alloc object was already created as part of flow setup on another uni of the onu for the same service.
457 // Just create gem ports and traffic queues on the current uni for the given service
458 logger.Infow(ctx, "alloc in use on another uni, schedulers already created, creating queues only",
459 log.Fields{"intf-id": sq.intfID,
460 "onu-id": sq.onuID,
461 "uni-id": sq.uniID,
462 "tp-id": sq.tpID,
463 "device-id": f.deviceHandler.device.Id})
464 // The upstream scheduler is already created. We only need to create the queues
465 // If there are multiple upstream flows on a given uni, then it is possible that
466 // we call pushTrafficQueues multiple times, but that is OK as BAL returns OK.
467 // TODO: Find better mechanism to not duplicate request.
468 if err = f.pushTrafficQueues(ctx, sq, TrafficSched); err != nil {
469 return olterrors.NewErrAdapter("failure-pushing-traffic-queues-to-device",
470 log.Fields{"intf-id": sq.intfID,
471 "direction": sq.direction,
472 "device-id": f.deviceHandler.device.Id}, err)
473 }
474 } else {
475 logger.Infow(ctx, "alloc not in use on another uni, only meter ref cnt updated",
476 log.Fields{"intf-id": sq.intfID,
477 "onu-id": sq.onuID,
478 "uni-id": sq.uniID,
479 "tp-id": sq.tpID,
480 "device-id": f.deviceHandler.device.Id})
481 }
482 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400483 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000484
Neha Sharma96b7bf22020-06-15 10:37:32 +0000485 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530486 log.Fields{
487 "meter-id": sq.meterID,
Girish Gowdra6071f382021-12-14 12:52:04 +0530488 "direction": direction,
Shrey Baid26912972020-04-16 21:02:31 +0530489 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000490
Girish Gowdraa482f272021-03-24 23:04:19 -0700491 found := false
492 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000493 if sq.flowMetadata != nil {
494 for _, meter := range sq.flowMetadata.Meters {
495 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700496 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700497 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 +0000498 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700499 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530500 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700501 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400502 break
503 }
504 }
505 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000506 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400507 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700508 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530509 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800510 "reason": "Could-not-get-meterbands-from-flowMetadata",
511 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530512 "meter-id": sq.meterID,
513 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400514 }
Gamze Abaka01174422021-03-10 06:55:27 +0000515
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700516 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530517 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
518 log.Fields{"intf-id": sq.intfID,
519 "direction": sq.direction,
520 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400521 }
522
salmansiddiqui7ac62132019-08-22 03:58:50 +0000523 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400524 * store the meter id on the KV store, for further reference.
525 */
Girish Gowdra6071f382021-12-14 12:52:04 +0530526 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530527 return olterrors.NewErrAdapter("failed-updating-meter-id",
528 log.Fields{"onu-id": sq.onuID,
529 "meter-id": sq.meterID,
530 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400531 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000532 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Girish Gowdra6071f382021-12-14 12:52:04 +0530533 log.Fields{"direction": direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700534 "meter-info": meterInfo,
535 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400536 return nil
537}
538
Girish Gowdraf3728b12022-02-02 21:46:51 -0800539func (f *OpenOltFlowMgr) pushTrafficQueues(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
540 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
541 if err != nil {
542 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
543 log.Fields{"intf-id": sq.intfID,
544 "direction": sq.direction,
545 "device-id": f.deviceHandler.device.Id}, err)
546 }
547 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
548 log.Fields{"direction": sq.direction,
549 "traffic-queues": trafficQueues,
550 "device-id": f.deviceHandler.device.Id})
551 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
552 UniId: sq.uniID, PortNo: sq.uniPort,
553 TrafficQueues: trafficQueues,
554 TechProfileId: TrafficSched[0].TechProfileId}
555 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
556 if len(queues.TrafficQueues) > 1 {
557 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
558 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
559 }
560 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
561 }
562 return err
563}
564
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700565func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700566 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000567
568 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530569 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
570 log.Fields{"intf-id": sq.intfID,
571 "direction": sq.direction,
572 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000573 }
574
Gamze Abakacb0e6772021-06-10 08:32:12 +0000575 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
576 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
577 log.Fields{
578 "direction": sq.direction,
579 "TrafficScheds": TrafficSched,
580 "device-id": f.deviceHandler.device.Id,
581 "intfID": sq.intfID,
582 "onuID": sq.onuID,
583 "uniID": sq.uniID})
584 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
585 IntfId: sq.intfID, OnuId: sq.onuID,
586 UniId: sq.uniID, PortNo: sq.uniPort,
587 TrafficScheds: TrafficSched}); err != nil {
588 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
589 }
590 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
591 "direction": sq.direction,
592 "traffic-queues": trafficQueues,
593 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000594 }
595
596 // On receiving the CreateTrafficQueues request, the driver should create corresponding
597 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000598 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530599 log.Fields{"direction": sq.direction,
600 "traffic-queues": trafficQueues,
601 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000602 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
603 UniId: sq.uniID, PortNo: sq.uniPort,
604 TrafficQueues: trafficQueues,
605 TechProfileId: TrafficSched[0].TechProfileId}
606 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
607 if len(queues.TrafficQueues) > 1 {
608 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
609 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
610 }
611 f.revertScheduler(ctx, sq, TrafficSched)
Shrey Baid26912972020-04-16 21:02:31 +0530612 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000613 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000614 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530615 "direction": sq.direction,
616 "traffic-queues": trafficQueues,
617 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000618
Esin Karamanccb714b2019-11-29 15:02:06 +0000619 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700620 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000621 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700622 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present { //assumed that there is only one queue per PON for the multicast service
Esin Karamanccb714b2019-11-29 15:02:06 +0000623 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
624 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000625 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000626 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700627 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000628 gemPortID: multicastQueuePerPonPort.GemportId,
629 servicePriority: multicastQueuePerPonPort.Priority,
630 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700631 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000632 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400633 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700634 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400635 return err
636 }
Shrey Baid26912972020-04-16 21:02:31 +0530637
Neha Sharma96b7bf22020-06-15 10:37:32 +0000638 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000639 }
640 }
641 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000642 return nil
643}
644
Girish Gowdraf3728b12022-02-02 21:46:51 -0800645// RemoveQueues removes the traffic queues from the device based on the given schedQueue info
646func (f *OpenOltFlowMgr) RemoveQueues(ctx context.Context, sq schedQueue) error {
647 var err error
648 logger.Infow(ctx, "removing-queue-in-olt",
649 log.Fields{
650 "direction": sq.direction,
651 "intf-id": sq.intfID,
652 "onu-id": sq.onuID,
653 "uni-id": sq.uniID,
654 "uni-port": sq.uniPort,
655 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400656
Girish Gowdraf3728b12022-02-02 21:46:51 -0800657 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
658 if err != nil {
659 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
660 log.Fields{
661 "intf-id": sq.intfID,
662 "direction": sq.direction,
663 "device-id": f.deviceHandler.device.Id}, err)
664 }
665
666 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
667 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
668 UniId: sq.uniID, PortNo: sq.uniPort,
669 TrafficQueues: TrafficQueues,
670 TechProfileId: sq.tpID}); err != nil {
671 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
672 log.Fields{
673 "intf-id": sq.intfID,
674 "traffic-queues": TrafficQueues,
675 "device-id": f.deviceHandler.device.Id}, err)
676 }
677 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
678
679 return err
680}
681
682// RemoveScheduler removes the traffic scheduler from the device based on the given schedQueue info
683func (f *OpenOltFlowMgr) RemoveScheduler(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400684 var Direction string
685 var SchedCfg *tp_pb.SchedulerConfig
686 var err error
Girish Gowdraf3728b12022-02-02 21:46:51 -0800687 logger.Infow(ctx, "removing-scheduler-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530688 log.Fields{
689 "direction": sq.direction,
690 "intf-id": sq.intfID,
691 "onu-id": sq.onuID,
692 "uni-id": sq.uniID,
693 "uni-port": sq.uniPort,
694 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000695 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700696 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400697 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000698 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700699 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400700 Direction = "downstream"
701 }
702
Girish Gowdraa482f272021-03-24 23:04:19 -0700703 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 -0400704
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700705 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000706 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000707
Girish Gowdraf3728b12022-02-02 21:46:51 -0800708 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
709 IntfId: sq.intfID, OnuId: sq.onuID,
710 UniId: sq.uniID, PortNo: sq.uniPort,
711 TrafficScheds: TrafficSched}); err != nil {
712 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530713 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800714 "intf-id": sq.intfID,
715 "traffic-schedulers": TrafficSched,
716 "onu-id": sq.onuID,
717 "uni-id": sq.uniID,
718 "uni-port": sq.uniPort}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000719 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400720
Girish Gowdraf3728b12022-02-02 21:46:51 -0800721 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
722 log.Fields{"device-id": f.deviceHandler.device.Id,
723 "intf-id": sq.intfID,
724 "onu-id": sq.onuID,
725 "uni-id": sq.uniID,
726 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400727
Girish Gowdraf3728b12022-02-02 21:46:51 -0800728 if sq.direction == tp_pb.Direction_UPSTREAM {
729 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
730 // Delete the TCONT on the ONU.
731 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
732 tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
733 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
734 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Gamze Abakacb0e6772021-06-10 08:32:12 +0000735 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800736 "intf": sq.intfID,
737 "onu-id": sq.onuID,
738 "uni-id": sq.uniID,
739 "device-id": f.deviceHandler.device.Id,
740 "alloc-id": allocID})
Gamze Abakacb0e6772021-06-10 08:32:12 +0000741 }
742 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000743
744 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400745 * delete the meter id on the KV store.
746 */
Girish Gowdraf3728b12022-02-02 21:46:51 -0800747 err = f.removeMeterReference(ctx, Direction, sq)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400748 return err
749}
750
Girish Gowdra197acc12021-08-16 10:59:45 -0700751// We are trying to force remove the schedulers and queues here if one exists for the given key.
752// We ignore any errors encountered in the process. The errors most likely are encountered when
753// the schedulers and queues are already cleared for the given key.
754func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
755
756 var schedCfg *tp_pb.SchedulerConfig
757 var err error
758 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
759 log.Fields{
760 "direction": sq.direction,
761 "intf-id": sq.intfID,
762 "onu-id": sq.onuID,
763 "uni-id": sq.uniID,
764 "uni-port": sq.uniPort,
765 "tp-id": sq.tpID,
766 "device-id": f.deviceHandler.device.Id})
767 if sq.direction == tp_pb.Direction_UPSTREAM {
768 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
769 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
770 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
771 }
772
773 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
774 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
775 TrafficSched[0].TechProfileId = sq.tpID
776
777 // Remove traffic queues. Ignore any errors, just log them.
778 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
779 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
780 "direction": sq.direction,
781 "intf-id": sq.intfID,
782 "onu-id": sq.onuID,
783 "uni-id": sq.uniID,
784 "uni-port": sq.uniPort,
785 "tp-id": sq.tpID,
786 "device-id": f.deviceHandler.device.Id,
787 "err": err})
788 } else {
789 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
790 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
791 UniId: sq.uniID, PortNo: sq.uniPort,
792 TrafficQueues: TrafficQueues,
793 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
794 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
795 "direction": sq.direction,
796 "intf-id": sq.intfID,
797 "onu-id": sq.onuID,
798 "uni-id": sq.uniID,
799 "uni-port": sq.uniPort,
800 "tp-id": sq.tpID,
801 "device-id": f.deviceHandler.device.Id,
802 "err": err})
803
804 } else {
805 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
806 "direction": sq.direction,
807 "intf-id": sq.intfID,
808 "onu-id": sq.onuID,
809 "uni-id": sq.uniID,
810 "uni-port": sq.uniPort,
811 "tp-id": sq.tpID})
812 }
813 }
814
815 // Remove traffic schedulers. Ignore any errors, just log them.
816 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
817 IntfId: sq.intfID, OnuId: sq.onuID,
818 UniId: sq.uniID, PortNo: sq.uniPort,
819 TrafficScheds: TrafficSched}); err != nil {
820 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
821 "direction": sq.direction,
822 "intf-id": sq.intfID,
823 "onu-id": sq.onuID,
824 "uni-id": sq.uniID,
825 "uni-port": sq.uniPort,
826 "tp-id": sq.tpID,
827 "device-id": f.deviceHandler.device.Id,
828 "err": err})
829 } else {
830 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
831 "direction": sq.direction,
832 "intf-id": sq.intfID,
833 "onu-id": sq.onuID,
834 "uni-id": sq.uniID,
835 "uni-port": sq.uniPort,
836 "tp-id": sq.tpID})
837 }
838}
839
Gamze Abakafee36392019-10-03 11:17:24 +0000840// This function allocates tconts and GEM ports for an ONU
khenaidoodc2116e2021-10-19 17:33:19 -0400841func (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 +0000842 var allocIDs []uint32
843 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530844 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530845 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000846 var err error
npujarec5762e2020-01-01 14:08:48 +0530847 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
848 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000849 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530850
Neha Sharma96b7bf22020-06-15 10:37:32 +0000851 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530852 "intf-id": intfID,
853 "onu-id": onuID,
854 "uni-id": uniID,
855 "device-id": f.deviceHandler.device.Id,
856 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530857
Manikkaraj kb1d51442019-07-23 10:41:02 -0400858 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700859 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000860 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000861 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530862 log.Fields{
863 "path": tpPath,
864 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700865 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000866 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530867 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000868 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530869 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700870 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530871 "tp-id": TpID,
872 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000873 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530874 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400875 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700876 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400877 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530878 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000879 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530880 log.Fields{
881 "uni": uni,
882 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530883 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530884 }
Gamze Abakafee36392019-10-03 11:17:24 +0000885
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700886 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700887 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700888 if UsMeterID != 0 {
889 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
890 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
891 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000892 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700893 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700894 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700895 "onu-id": onuID,
896 "uni-id": uniID,
897 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700898 "meter-id": UsMeterID,
899 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000900 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700901 return 0, nil, nil
902 }
903 }
904 if DsMeterID != 0 {
905 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
906 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
907 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000908 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700909 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700910 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700911 "onu-id": onuID,
912 "uni-id": uniID,
913 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700914 "meter-id": DsMeterID,
915 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000916 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700917 return 0, nil, nil
918 }
919 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700920 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700921 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700922 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700923 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700924 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000925
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700926 if tpInstanceExists {
927 return allocID, gemPortIDs, techProfileInstance
928 }
929
930 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700931 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700932 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000933 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700934 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700935 "intf-id": intfID,
936 "onu-id": onuID,
937 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700938 "alloc-ids": allocIDs,
939 "gemports": allgemPortIDs,
940 "device-id": f.deviceHandler.device.Id})
941 // Send Tconts and GEM ports to KV store
942 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530943 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400944 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700945 // CreateSchedulerQueues for EPON needs to be implemented here
946 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700947 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700948 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700949 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700950 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700951 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700952
953 if tpInstanceExists {
954 return allocID, gemPortIDs, techProfileInstance
955 }
956
957 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700958 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700959 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000960 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700961 log.Fields{
962 "alloc-ids": allocIDs,
963 "gemports": allgemPortIDs,
964 "device-id": f.deviceHandler.device.Id})
965 // Send Tconts and GEM ports to KV store
966 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
967 return allocID, gemPortIDs, techProfileInstance
968 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000969 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700970 log.Fields{
971 "tpInst": tpInst})
972 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530973 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530974}
975
npujarec5762e2020-01-01 14:08:48 +0530976func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530977
Neha Sharma96b7bf22020-06-15 10:37:32 +0000978 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530979 log.Fields{
980 "intf-id": intfID,
981 "onu-id": onuID,
982 "uni-id": uniID,
983 "alloc-id": allocID,
984 "gemport-ids": gemPortIDs,
985 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530986 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530987 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000988 logger.Errorw(ctx, "error-while-uploading-allocid-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530989 }
npujarec5762e2020-01-01 14:08:48 +0530990 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000991 logger.Errorw(ctx, "error-while-uploading-gemports-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530992 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700993
Neha Sharma96b7bf22020-06-15 10:37:32 +0000994 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 -0400995 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530996 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400997 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530998}
999
Girish Gowdra4736e5c2021-08-25 15:19:10 -07001000func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +05301001 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001002 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07001003 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
1004 var err error
1005 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
1006 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
1007 if err != nil || f.techprofile == nil {
1008 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
1009 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
1010 }
1011 logger.Debugw(ctx, "init-tech-profile-done",
1012 log.Fields{
1013 "intf-id": intfID,
1014 "device-id": f.deviceHandler.device.Id})
1015 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -07001016 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301017 }
1018 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07001019 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
1020 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 +05301021}
1022
Gamze Abaka7650be62021-02-26 10:50:36 +00001023func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Andrea Campanellafaa42152021-10-28 11:50:56 +05301024 flowContext.classifier[PacketTagType] = SingleTag // FIXME: This hardcoding needs to be removed.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001025 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301026 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001027 "uplinkClassifier": flowContext.classifier,
1028 "uplinkAction": flowContext.action})
1029 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +05301030 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +05301031}
1032
Gamze Abaka7650be62021-02-26 10:50:36 +00001033func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
1034 downlinkClassifier := flowContext.classifier
1035 downlinkAction := flowContext.action
1036
Andrea Campanellafaa42152021-10-28 11:50:56 +05301037 // TODO: For now mark the PacketTagType as SingleTag when OLT is transparent to VLAN
1038 // Per some deployment models, it is also possible that ONU operates on double tagged packets,
1039 // so this hardcoding of SingeTag packet-tag-type may be problem for such deployment models.
1040 // Need a better way for detection of packet tag type from OpenFlow message.
1041 if _, ok := downlinkClassifier[VlanVid]; !ok {
1042 downlinkClassifier[PacketTagType] = SingleTag
1043 } else {
1044 downlinkClassifier[PacketTagType] = DoubleTag
1045 downlinkAction[PopVlan] = true
1046 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001047 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301048 log.Fields{
1049 "downlinkClassifier": downlinkClassifier,
1050 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001051 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
1052 if vlan, exists := downlinkClassifier[VlanVid]; exists {
1053 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -07001054 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001055 if uint32(metadata.(uint64)) == plt.MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001056 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301057 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001058 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301059 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +00001060 "onu-id": flowContext.onuID,
1061 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001062 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -04001063 }
1064 }
1065 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301066 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001067
Matt Jeannereted16b7c2019-11-01 13:31:35 -04001068 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1069 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +05301070 if ok {
1071 downlinkAction[VlanVid] = dlClVid & 0xfff
Girish Gowdra26f344b2019-10-23 14:39:13 +05301072 }
1073
Gamze Abaka7650be62021-02-26 10:50:36 +00001074 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301075}
1076
Gamze Abaka7650be62021-02-26 10:50:36 +00001077func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001078
Gamze Abaka7650be62021-02-26 10:50:36 +00001079 intfID := flowContext.intfID
1080 onuID := flowContext.onuID
1081 uniID := flowContext.uniID
1082 classifier := flowContext.classifier
1083 action := flowContext.action
1084 allocID := flowContext.allocID
1085 gemPortID := flowContext.gemPortID
1086 tpID := flowContext.tpID
1087 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001088 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301089 log.Fields{
1090 "intf-id": intfID,
1091 "onu-id": onuID,
1092 "uni-id": uniID,
1093 "device-id": f.deviceHandler.device.Id,
1094 "classifier": classifier,
1095 "action": action,
1096 "direction": direction,
1097 "alloc-id": allocID,
1098 "gemport-id": gemPortID,
1099 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001100
1101 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001102 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301103 log.Fields{
1104 "device-id": f.deviceHandler.device.Id,
1105 "intf-id": intfID,
1106 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001107 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301108 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001109 classifierProto, err := makeOpenOltClassifierField(classifier)
1110 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301111 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301112 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001113 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301114 log.Fields{
1115 "classifier": *classifierProto,
1116 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001117 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001118 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301119 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301120 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001121 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301122 log.Fields{
1123 "action": *actionProto,
1124 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001125 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301126 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301127 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001128 log.Fields{
1129 "classifier": classifier,
1130 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301131 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001132 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301133 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001134
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001135 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001136 OnuId: int32(onuID),
1137 UniId: int32(uniID),
1138 FlowId: logicalFlow.Id,
1139 FlowType: direction,
1140 AllocId: int32(allocID),
1141 NetworkIntfId: int32(networkIntfID),
1142 GemportId: int32(gemPortID),
1143 Classifier: classifierProto,
1144 Action: actionProto,
1145 Priority: int32(logicalFlow.Priority),
1146 Cookie: logicalFlow.Cookie,
1147 PortNo: flowContext.portNo,
1148 TechProfileId: tpID,
1149 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1150 PbitToGemport: flowContext.pbitToGem,
1151 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001152 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001153 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001154 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301155 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001156 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301157 log.Fields{"direction": direction,
1158 "device-id": f.deviceHandler.device.Id,
1159 "flow": flow,
1160 "intf-id": intfID,
1161 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001162
David K. Bainbridge794735f2020-02-11 21:01:37 -08001163 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301164}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001165
Gamze Abaka7650be62021-02-26 10:50:36 +00001166func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1167
1168 intfID := flowContext.intfID
1169 onuID := flowContext.onuID
1170 uniID := flowContext.uniID
1171 logicalFlow := flowContext.logicalFlow
1172 classifier := flowContext.classifier
1173 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301174
Neha Sharma96b7bf22020-06-15 10:37:32 +00001175 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301176 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301177 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001178 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301179 "action": action,
1180 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001181 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301182 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301183
1184 // Clear the action map
1185 for k := range action {
1186 delete(action, k)
1187 }
1188
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001189 action[TrapToHost] = true
1190 classifier[UDPSrc] = uint32(68)
1191 classifier[UDPDst] = uint32(67)
1192 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301193
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001194 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001195 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301196 log.Fields{
1197 "device-id": f.deviceHandler.device.Id,
1198 "intf-id": intfID,
1199 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001200 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301201 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301202
Neha Sharma96b7bf22020-06-15 10:37:32 +00001203 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301204 log.Fields{
1205 "ul_classifier": classifier,
1206 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001207 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301208 "intf-id": intfID,
1209 "onu-id": onuID,
1210 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301211
David K. Bainbridge794735f2020-02-11 21:01:37 -08001212 classifierProto, err := makeOpenOltClassifierField(classifier)
1213 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301214 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301215 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001216 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001217 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001218 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301219 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301220 }
1221
David K. Bainbridge794735f2020-02-11 21:01:37 -08001222 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001223 OnuId: int32(onuID),
1224 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001225 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001226 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001227 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001228 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001229 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301230 Classifier: classifierProto,
1231 Action: actionProto,
1232 Priority: int32(logicalFlow.Priority),
1233 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001234 PortNo: flowContext.portNo,
1235 TechProfileId: flowContext.tpID,
1236 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1237 PbitToGemport: flowContext.pbitToGem,
1238 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001239 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001240 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001241 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001242 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001243 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301244 log.Fields{
1245 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001246 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301247 "intf-id": intfID,
1248 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301249
David K. Bainbridge794735f2020-02-11 21:01:37 -08001250 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301251}
1252
Esin Karamanae41e2b2019-12-17 18:13:13 +00001253//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001254func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1255 delete(flowContext.classifier, VlanVid)
1256 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001257}
1258
1259//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001260func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1261
1262 intfID := flowContext.intfID
1263 onuID := flowContext.onuID
1264 uniID := flowContext.uniID
1265 logicalFlow := flowContext.logicalFlow
1266 classifier := flowContext.classifier
1267 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001268
Neha Sharma96b7bf22020-06-15 10:37:32 +00001269 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001270 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301271 return olterrors.NewErrNotFound("nni-interface-id",
1272 log.Fields{
1273 "classifier": classifier,
1274 "action": action,
1275 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001276 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001277 }
1278
1279 // Clear the action map
1280 for k := range action {
1281 delete(action, k)
1282 }
1283
1284 action[TrapToHost] = true
1285 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001286
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001287 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001288 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001289 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001290 }
1291
Neha Sharma96b7bf22020-06-15 10:37:32 +00001292 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301293 log.Fields{
1294 "ul_classifier": classifier,
1295 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001296 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301297 "device-id": f.deviceHandler.device.Id,
1298 "intf-id": intfID,
1299 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001300
David K. Bainbridge794735f2020-02-11 21:01:37 -08001301 classifierProto, err := makeOpenOltClassifierField(classifier)
1302 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301303 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001304 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001305 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301306 log.Fields{
1307 "classifier": *classifierProto,
1308 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001309 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301311 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001312 }
1313
David K. Bainbridge794735f2020-02-11 21:01:37 -08001314 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001315 OnuId: int32(onuID),
1316 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001317 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001318 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001319 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001320 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001321 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001322 Classifier: classifierProto,
1323 Action: actionProto,
1324 Priority: int32(logicalFlow.Priority),
1325 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001326 PortNo: flowContext.portNo,
1327 TechProfileId: flowContext.tpID,
1328 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1329 PbitToGemport: flowContext.pbitToGem,
1330 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001331 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001332
David K. Bainbridge794735f2020-02-11 21:01:37 -08001333 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001334 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 -08001335 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001336
David K. Bainbridge794735f2020-02-11 21:01:37 -08001337 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001338}
1339
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001340// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001341func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1342 intfID := flowContext.intfID
1343 onuID := flowContext.onuID
1344 uniID := flowContext.uniID
1345 portNo := flowContext.portNo
1346 allocID := flowContext.allocID
1347 gemPortID := flowContext.gemPortID
1348 logicalFlow := flowContext.logicalFlow
1349 classifier := flowContext.classifier
1350 action := flowContext.action
1351
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001352 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301353 log.Fields{
1354 "intf-id": intfID,
1355 "onu-id": onuID,
1356 "port-no": portNo,
1357 "alloc-id": allocID,
1358 "gemport-id": gemPortID,
1359 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001360 "flow": logicalFlow,
1361 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301362
1363 uplinkClassifier := make(map[string]interface{})
1364 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301365
manikkaraj kbf256be2019-03-25 00:13:48 +05301366 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001367 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001368 uplinkClassifier[PacketTagType] = SingleTag
1369 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001370 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301371 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001372 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001373 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001374 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301375 "device-id": f.deviceHandler.device.Id,
1376 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001377 "intf-id": intfID,
1378 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001379 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301380 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001381 //Add Uplink EthType Flow
1382 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301383 log.Fields{
1384 "ul_classifier": uplinkClassifier,
1385 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001386 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301387 "device-id": f.deviceHandler.device.Id,
1388 "intf-id": intfID,
1389 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301390
David K. Bainbridge794735f2020-02-11 21:01:37 -08001391 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1392 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301393 return olterrors.NewErrInvalidValue(log.Fields{
1394 "classifier": uplinkClassifier,
1395 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301396 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001397 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301398 log.Fields{
1399 "classifier": *classifierProto,
1400 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001401 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001402 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301403 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301404 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001405 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301406 log.Fields{
1407 "action": *actionProto,
1408 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001409 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301410 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301411 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001412 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301413 "action": action,
1414 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001415 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301416 }
1417
David K. Bainbridge794735f2020-02-11 21:01:37 -08001418 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001419 OnuId: int32(onuID),
1420 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001421 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001422 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001423 AllocId: int32(allocID),
1424 NetworkIntfId: int32(networkIntfID),
1425 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301426 Classifier: classifierProto,
1427 Action: actionProto,
1428 Priority: int32(logicalFlow.Priority),
1429 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001430 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001431 TechProfileId: flowContext.tpID,
1432 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1433 PbitToGemport: flowContext.pbitToGem,
1434 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001435 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001436 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001437 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001438 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001439 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301440 log.Fields{
1441 "device-id": f.deviceHandler.device.Id,
1442 "onu-id": onuID,
1443 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001444 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301445 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001446
David K. Bainbridge794735f2020-02-11 21:01:37 -08001447 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301448}
1449
David K. Bainbridge794735f2020-02-11 21:01:37 -08001450func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001451 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001452
1453 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1454 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1455 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001456 if vlanID != ReservedVlan {
1457 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001458 classifier.OVid = vid
1459 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301460 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301461 // The classifierInfo[Metadata] carries the vlan that the OLT see when it receives packet from the ONU
David K. Bainbridge82efc492019-09-04 09:57:11 -07001462 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1463 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301464 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1465 // If OLT is using transparent tag mechanism, then it classifies whatever tag it sees to/from ONU which
1466 //is OVid from the perspective of the OLT. When OLT also places or pops the outer tag, then classifierInfo[Metadata]
1467 // becomes the IVid.
1468 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1469 if vid != ReservedVlan {
1470 classifier.IVid = vid
1471 }
1472 } else {
1473 if vid != ReservedVlan {
1474 classifier.OVid = vid
1475 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001476 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301477 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301478 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001479 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301480 classifier.OPbits = vlanPcp
1481 } else {
1482 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301483 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001484 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1485 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1486 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1487 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001488 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001489 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1490 classifier.PktTagType = pktTagType
1491
1492 switch pktTagType {
1493 case SingleTag:
1494 case DoubleTag:
1495 case Untagged:
1496 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001497 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301498 }
1499 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001500 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301501}
1502
Gamze Abaka724d0852020-03-18 12:10:24 +00001503func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001504 var actionCmd openoltpb2.ActionCmd
1505 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301506 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001507 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301508 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001509 if _, ok := actionInfo[VlanPcp]; ok {
1510 action.Cmd.RemarkInnerPbits = true
1511 action.IPbits = actionInfo[VlanPcp].(uint32)
1512 if _, ok := actionInfo[VlanVid]; ok {
1513 action.Cmd.TranslateInnerTag = true
1514 action.IVid = actionInfo[VlanVid].(uint32)
1515 }
1516 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001517 } else if _, ok := actionInfo[PushVlan]; ok {
1518 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301519 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001520 if _, ok := actionInfo[VlanPcp]; ok {
1521 action.OPbits = actionInfo[VlanPcp].(uint32)
1522 action.Cmd.RemarkOuterPbits = true
1523 if _, ok := classifierInfo[VlanVid]; ok {
1524 action.IVid = classifierInfo[VlanVid].(uint32)
1525 action.Cmd.TranslateInnerTag = true
1526 }
1527 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001528 } else if _, ok := actionInfo[TrapToHost]; ok {
1529 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301530 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301531 // When OLT is transparent to vlans no-action is valid.
1532 /*
1533 else {
1534 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1535 }
1536 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001537 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301538}
1539
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001540// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001541func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001542 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301543}
1544
Gamze Abakafee36392019-10-03 11:17:24 +00001545// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001546// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1547// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1548// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1549// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1550// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1551// because it was observed that if the ONU device was deleted too soon after the flows were
1552// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1553// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1554// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001555func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301556 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001557 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1558
Gamze Abakafee36392019-10-03 11:17:24 +00001559 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001560
1561 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001562 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001563 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1564 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
1565 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1566 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1567 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1568 log.Fields{
1569 "tp-id": tpID,
1570 "path": tpPath})
1571 }
1572 switch tpInstance := tpInst.(type) {
1573 case *tp_pb.TechProfileInstance:
1574 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1575 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1576 }
1577 // Force cleanup scheduler/queues -- end
1578
1579 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301580 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001581 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301582 // return err
1583 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001584 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001585 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 +00001586 }
1587 return nil
1588}
1589
1590// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301591func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001592 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001593 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001594 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001595 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301596 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1597 log.Fields{
1598 "tp-id": tpID,
1599 "uni-port-name": uniPortName,
1600 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001601 }
1602 return nil
1603}
1604
David K. Bainbridge794735f2020-02-11 21:01:37 -08001605func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001606
1607 var intfID uint32
1608 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1609 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1610 */
1611 if deviceFlow.AccessIntfId != -1 {
1612 intfID = uint32(deviceFlow.AccessIntfId)
1613 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001614 // We need to log the valid interface ID.
1615 // 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 +00001616 intfID = uint32(deviceFlow.NetworkIntfId)
1617 }
1618
Neha Sharma96b7bf22020-06-15 10:37:32 +00001619 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301620 "flow": *deviceFlow,
1621 "device-id": f.deviceHandler.device.Id,
1622 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001623 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001624
1625 st, _ := status.FromError(err)
1626 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001627 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001628 "err": err,
1629 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301630 "device-id": f.deviceHandler.device.Id,
1631 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001632 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301633 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001634
1635 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001636 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301637 log.Fields{"err": err,
1638 "device-flow": deviceFlow,
1639 "device-id": f.deviceHandler.device.Id,
1640 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001641 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001642 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001643 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301644 log.Fields{
1645 "flow": *deviceFlow,
1646 "device-id": f.deviceHandler.device.Id,
1647 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001648
1649 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1650 if deviceFlow.AccessIntfId != -1 {
1651 // No need to register the flow if it is a trap on nni flow.
1652 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1653 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1654 return err
1655 }
1656 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001657 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001658}
1659
Neha Sharma96b7bf22020-06-15 10:37:32 +00001660func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1661 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301662 log.Fields{
1663 "flow": *deviceFlow,
1664 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001665 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001666 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001667 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001668 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301669 log.Fields{
1670 "err": err,
1671 "deviceFlow": deviceFlow,
1672 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001673 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001674 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001675 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001676 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001677
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001678 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001679 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001680 "of-flow-id": ofFlowID,
1681 "flow": *deviceFlow,
1682 "device-id": f.deviceHandler.device.Id,
1683 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001684 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301685}
1686
David K. Bainbridge794735f2020-02-11 21:01:37 -08001687func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001688
1689 classifierInfo := make(map[string]interface{})
1690 actionInfo := make(map[string]interface{})
1691
1692 classifierInfo[EthType] = uint32(LldpEthType)
1693 classifierInfo[PacketTagType] = Untagged
1694 actionInfo[TrapToHost] = true
1695
1696 // LLDP flow is installed to trap LLDP packets on the NNI port.
1697 // We manage flow_id resource pool on per PON port basis.
1698 // Since this situation is tricky, as a hack, we pass the NNI port
1699 // index (network_intf_id) as PON port Index for the flow_id resource
1700 // pool. Also, there is no ONU Id available for trapping LLDP packets
1701 // on NNI port, use onu_id as -1 (invalid)
1702 // ****************** CAVEAT *******************
1703 // This logic works if the NNI Port Id falls within the same valid
1704 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1705 // we need to have a re-look at this.
1706 // *********************************************
1707
1708 var onuID = -1
1709 var uniID = -1
1710 var gemPortID = -1
1711
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001712 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001713 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301714 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001715 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001716 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001717 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001718 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001719 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001720
David K. Bainbridge794735f2020-02-11 21:01:37 -08001721 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1722 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301723 return olterrors.NewErrInvalidValue(
1724 log.Fields{
1725 "classifier": classifierInfo,
1726 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001727 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001728 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301729 log.Fields{
1730 "classifier": *classifierProto,
1731 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001732 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001733 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301734 return olterrors.NewErrInvalidValue(
1735 log.Fields{
1736 "action": actionInfo,
1737 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001738 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001739 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301740 log.Fields{
1741 "action": *actionProto,
1742 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001743
1744 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1745 OnuId: int32(onuID), // OnuId not required
1746 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001747 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001748 FlowType: Downstream,
1749 NetworkIntfId: int32(networkInterfaceID),
1750 GemportId: int32(gemPortID),
1751 Classifier: classifierProto,
1752 Action: actionProto,
1753 Priority: int32(flow.Priority),
1754 Cookie: flow.Cookie,
1755 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001756 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001757 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301758 log.Fields{
1759 "flow": downstreamflow,
1760 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001761 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001762 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301763 log.Fields{
1764 "device-id": f.deviceHandler.device.Id,
1765 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001766 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001767
David K. Bainbridge794735f2020-02-11 21:01:37 -08001768 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301769}
1770
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001771func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1772 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001773}
1774
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001775//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001776func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001777 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1778 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1779 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001780 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301781 log.Fields{
1782 "intf-id": intfID,
1783 "onu-id": onuID,
1784 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001785 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001786 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301787 return nil, olterrors.NewErrNotFound("onu-child-device",
1788 log.Fields{
1789 "onu-id": onuID,
1790 "intf-id": intfID,
1791 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001792 }
khenaidoo106c61a2021-08-11 18:05:46 -04001793 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001794 //better to ad the device to cache here.
1795 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1796 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001797 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301798 log.Fields{
1799 "intf-id": intfID,
1800 "onu-id": onuID,
1801 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001802 }
1803
1804 return onuDev.(*OnuDevice), nil
1805}
1806
1807//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001808func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1809 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301810 log.Fields{
1811 "pon-port": intfID,
1812 "onu-id": onuID,
1813 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001814 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001815 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001816 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301817 return nil, olterrors.NewErrNotFound("onu",
1818 log.Fields{
1819 "interface-id": parentPortNo,
1820 "onu-id": onuID,
1821 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001822 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301823 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001824 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301825 log.Fields{
1826 "device-id": f.deviceHandler.device.Id,
1827 "child_device_id": onuDevice.Id,
1828 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301829 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301830}
1831
Neha Sharma96b7bf22020-06-15 10:37:32 +00001832func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1833 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301834 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001835 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301836 log.Fields{
1837 "intf-id": intfID,
1838 "onu-id": onuID,
1839 "uni-id": uniID,
1840 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001841 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301842 }
1843
khenaidoodc2116e2021-10-19 17:33:19 -04001844 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001845 DeviceId: onuDev.deviceID,
1846 UniId: uniID,
1847 TpInstancePath: tpPath,
1848 GemPortId: gemPortID,
1849 }
1850 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1851
1852 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301853 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1854 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001855 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1856 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301857 "onu-id": onuDev.deviceID,
1858 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001859 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301860 }
khenaidoo106c61a2021-08-11 18:05:46 -04001861
Neha Sharma96b7bf22020-06-15 10:37:32 +00001862 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301863 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001864 "msg": delGemPortMsg,
1865 "from-adapter": f.deviceHandler.device.Type,
1866 "to-adapter": onuDev.deviceType,
1867 "device-id": f.deviceHandler.device.Id,
1868 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301869 return nil
1870}
1871
Neha Sharma96b7bf22020-06-15 10:37:32 +00001872func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1873 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301874 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001875 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301876 log.Fields{
1877 "intf-id": intfID,
1878 "onu-id": onuID,
1879 "uni-id": uniID,
1880 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001881 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301882 }
1883
khenaidoodc2116e2021-10-19 17:33:19 -04001884 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001885 DeviceId: onuDev.deviceID,
1886 UniId: uniID,
1887 TpInstancePath: tpPath,
1888 AllocId: allocID,
1889 }
1890
Neha Sharma96b7bf22020-06-15 10:37:32 +00001891 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301892 log.Fields{
1893 "msg": *delTcontMsg,
1894 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001895
1896 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301897 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1898 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001899 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1900 "to-adapter": onuDev.adapterEndpoint,
1901 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301902 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001903 "device-id": f.deviceHandler.device.Id}, err)
1904
Girish Gowdra6b130582019-11-20 16:45:20 +05301905 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001906 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301907 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001908 "msg": delTcontMsg,
1909 "device-id": f.deviceHandler.device.Id,
1910 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301911 return nil
1912}
1913
Girish Gowdrac3037402020-01-22 20:29:53 +05301914// Once the gemport is released for a given onu, it also has to be cleared from local cache
1915// which was used for deriving the gemport->logicalPortNo during packet-in.
1916// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1917// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001918func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001919 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301920 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001921 "gem-port-id": gemPortID,
1922 "intf-id": intfID,
1923 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001924 "device-id": f.deviceHandler.device.Id})
1925 f.onuGemInfoLock.RLock()
1926 onugem, ok := f.onuGemInfoMap[onuID]
1927 f.onuGemInfoLock.RUnlock()
1928 if !ok {
1929 logger.Warnw(ctx, "onu gem info already cleared from cache", log.Fields{
1930 "gem-port-id": gemPortID,
1931 "intf-id": intfID,
1932 "onu-id": onuID,
1933 "device-id": f.deviceHandler.device.Id})
1934 return
1935 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001936deleteLoop:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001937 for j, gem := range onugem.GemPorts {
1938 // If the gemport is found, delete it from local cache.
1939 if gem == gemPortID {
1940 onugem.GemPorts = append(onugem.GemPorts[:j], onugem.GemPorts[j+1:]...)
1941 f.onuGemInfoLock.Lock()
1942 f.onuGemInfoMap[onuID] = onugem
1943 f.onuGemInfoLock.Unlock()
1944 logger.Infow(ctx, "removed-gemport-from-local-cache",
1945 log.Fields{
1946 "intf-id": intfID,
1947 "onu-id": onuID,
1948 "deletedgemport-id": gemPortID,
1949 "gemports": onugem.GemPorts,
1950 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001951 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301952 }
1953 }
1954}
1955
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301956//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001957// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001958func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Gamze Abaka411ef2f2021-11-22 08:38:08 +00001959 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001960
1961 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001962
Girish Gowdraa482f272021-03-24 23:04:19 -07001963 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1964 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001965 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1966 log.Fields{
1967 "tpPath": tpPath,
1968 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001969
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001970 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001971 if err != nil || techprofileInst == nil {
1972 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1973 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1974 if childDevice == nil {
1975 // happens when subscriber un-provision is immediately followed by child device delete
1976 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1977 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1978 return nil
1979 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001980 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1981 log.Fields{
1982 "tp-id": tpID,
1983 "path": tpPath}, err)
1984 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001985
1986 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001987 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001988 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001989 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1990 gemPortID := gemPort.GemportId
1991 used := f.isGemPortUsedByAnotherFlow(gemPortID, flowID)
1992 if used {
1993 f.gemToFlowIDsKey.RLock()
1994 flowIDs := f.gemToFlowIDs[gemPortID]
1995 f.gemToFlowIDsKey.RUnlock()
1996
1997 for i, flowIDinMap := range flowIDs {
1998 if flowIDinMap == flowID {
1999 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
2000 f.gemToFlowIDsKey.Lock()
2001 f.gemToFlowIDs[gemPortID] = flowIDs
2002 f.gemToFlowIDsKey.Unlock()
2003 // everytime gemToFlowIDs cache is updated the same should be updated
2004 // in kv store by calling UpdateFlowIDsForGem
2005 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, gemPortID, flowIDs); err != nil {
2006 return err
2007 }
2008 break
2009 }
2010 }
2011 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
2012 log.Fields{
2013 "gemport-id": gemPortID,
2014 "usedByFlows": flowIDs,
2015 "currentFlow": flowID,
2016 "device-id": f.deviceHandler.device.Id})
2017 allGemPortsFree = false
2018 }
2019 }
2020 if !allGemPortsFree {
2021 return nil
2022 }
2023 }
2024
2025 logger.Debugw(ctx, "all-gem-ports-are-free-to-be-deleted", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Girish Gowdraf3728b12022-02-02 21:46:51 -08002026
2027 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
Gamze Abaka745ccb72021-11-18 11:29:58 +00002028 switch techprofileInst := techprofileInst.(type) {
2029 case *tp_pb.TechProfileInstance:
Girish Gowdraf3728b12022-02-02 21:46:51 -08002030 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
2031 logger.Warn(ctx, err)
2032 }
2033 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2034 logger.Warn(ctx, err)
2035 }
2036
2037 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2038 gemPortID := gemPort.GemportId
2039 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), gemPortID)
2040 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), gemPortID) // ignore error and proceed.
2041
2042 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gemPortID); err == nil {
2043 //everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
2044 // by calling DeleteFlowIDsForGem
2045 f.gemToFlowIDsKey.Lock()
2046 delete(f.gemToFlowIDs, gemPortID)
2047 f.gemToFlowIDsKey.Unlock()
2048 } else {
2049 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
2050 log.Fields{
2051 "err": err,
2052 "intf": intfID,
2053 "onu-id": onuID,
2054 "uni-id": uniID,
2055 "device-id": f.deviceHandler.device.Id,
2056 "gemport-id": gemPortID})
2057 }
2058
2059 }
2060 // Remove queues at OLT in upstream and downstream direction
2061 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2062 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
2063 logger.Warn(ctx, err)
2064 }
2065 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
2066 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
2067 logger.Warn(ctx, err)
2068 }
2069 }
2070
2071 switch techprofileInst := techprofileInst.(type) {
2072 case *tp_pb.TechProfileInstance:
2073 // 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
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002074 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2075 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQueue)
2076 if !allocExists {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002077 // all alloc object references removed, remove upstream scheduler
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002078 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002079 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002080 logger.Warn(ctx, err)
2081 }
2082 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002083 // remove alloc id from resource pool by setting the 'freeFromResourcePool' to true
2084 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, true)
2085 } else {
2086 // just remove meter reference for the upstream direction for the current pon/onu/uni
2087 // 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
2088 if err := f.removeMeterReference(ctx, "upstream", schedQueue); err != nil {
2089 return err
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002090 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002091 // setting 'freeFromResourcePool' to false in resourceMgr.FreeAllocID will only remove alloc-id data for the given pon/onu/uni
2092 // but still preserve it on the resource pool.
2093 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, false)
2094 }
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002095
Girish Gowdraf3728b12022-02-02 21:46:51 -08002096 // Downstream scheduler removal is simple, just invoke RemoveScheduler without all the complex handling we do for the alloc object.
2097 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
2098 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
2099 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
2100 logger.Warn(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002101 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002102 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002103 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07002104 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002105 logger.Warn(ctx, err)
2106 }
Girish Gowdraa482f272021-03-24 23:04:19 -07002107 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002108 logger.Warn(ctx, err)
2109 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002110 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002111 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002112 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302113 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002114 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302115 "onu-id": onuID,
2116 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002117 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002118 "alloc-id": techprofileInst.AllocId,
2119 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002120 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002121 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, true)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002122 default:
2123 logger.Errorw(ctx, "error-unknown-tech",
2124 log.Fields{
2125 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002126 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002127
2128 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
2129 switch techprofileInst := techprofileInst.(type) {
2130 case *tp_pb.TechProfileInstance:
2131 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2132 // Delete the gem port on the ONU.
2133 if sendDeleteGemRequest {
2134 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId, tpPath); err != nil {
2135 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2136 log.Fields{
2137 "err": err,
2138 "intfID": intfID,
2139 "onu-id": onuID,
2140 "uni-id": uniID,
2141 "device-id": f.deviceHandler.device.Id,
2142 "gemport-id": gemPort.GemportId})
2143 }
2144 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId)
2145 }
2146 }
2147 }
2148
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302149 return nil
2150}
2151
David K. Bainbridge794735f2020-02-11 21:01:37 -08002152// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002153func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002154 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302155 log.Fields{
2156 "flowDirection": flowDirection,
2157 "flow": *flow,
2158 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002159
2160 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002161 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002162 }
2163
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302164 var ethType, ipProto, inPort uint32
2165 for _, field := range flows.GetOfbFields(flow) {
2166 if field.Type == flows.IP_PROTO {
2167 ipProto = field.GetIpProto()
2168 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"ipProto": ipProto})
2169 } else if field.Type == flows.ETH_TYPE {
2170 ethType = field.GetEthType()
2171 logger.Debugw(ctx, "field-type-eth-type", log.Fields{"ethType": ethType})
2172 } else if field.Type == flows.IN_PORT {
2173 inPort = field.GetPort()
2174 logger.Debugw(ctx, "field-type-in-port", log.Fields{"inPort": inPort})
2175 }
2176 }
2177 portType := plt.IntfIDToPortTypeName(inPort)
2178 if (ethType == uint32(LldpEthType) || ipProto == uint32(IPProtoDhcp) || ipProto == uint32(IgmpProto)) &&
2179 (portType == voltha.Port_ETHERNET_NNI) {
2180 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: -1, OnuId: -1, UniId: -1, TechProfileId: 0, FlowType: Downstream}
2181 logger.Debugw(ctx, "nni-trap-flow-to-be-deleted", log.Fields{"flow": flow})
2182 return f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id)
2183 // No more processing needed for trap from nni flows.
2184 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302185
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302186 portNum, Intf, onu, uni, _, _, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302187 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002188 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002189 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302190 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002191 onuID := int32(onu)
2192 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002193 tpID, err := getTpIDFromFlow(ctx, flow)
2194 if err != nil {
2195 return olterrors.NewErrNotFound("tp-id",
2196 log.Fields{
2197 "flow": flow,
2198 "intf-id": Intf,
2199 "onu-id": onuID,
2200 "uni-id": uniID,
2201 "device-id": f.deviceHandler.device.Id}, err)
2202 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302203
Neha Sharma96b7bf22020-06-15 10:37:32 +00002204 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302205 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002206 "flow-id": flow.Id,
2207 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302208 "onu-id": onuID,
2209 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302210
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002211 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2212 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002213 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2214 return err
2215 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002216
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002217 // Delete the flow-id to gemport list entry from the map now the flow is deleted.
Gamze Abaka745ccb72021-11-18 11:29:58 +00002218 f.flowIDToGemsLock.Lock()
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002219 delete(f.flowIDToGems, flow.Id)
2220 f.flowIDToGemsLock.Unlock()
2221
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002222 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002223 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2224 "flow-id": flow.Id,
2225 "device-id": f.deviceHandler.device.Id,
2226 "onu-id": onuID,
2227 "intf": Intf,
2228 "err": err,
2229 })
2230 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302231 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002232
Girish Gowdra82c80982021-03-26 16:22:02 -07002233 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2234 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2235 return err
2236 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002237 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002238}
2239
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002240//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002241func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002242
Matteo Scandolof16389e2021-05-18 00:47:08 +00002243 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302244 var direction string
2245 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002246
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302247 for _, action := range flows.GetActions(flow) {
2248 if action.Type == flows.OUTPUT {
2249 if out := action.GetOutput(); out != nil {
2250 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002251 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302252 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002253 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002254 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002255 }
2256 }
2257 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002258
2259 if flows.HasGroup(flow) {
2260 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002261 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002262 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302263 direction = Upstream
2264 } else {
2265 direction = Downstream
2266 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302267
Girish Gowdracefae192020-03-19 18:14:10 -07002268 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002269 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002270
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002271 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002272}
2273
Esin Karamanae41e2b2019-12-17 18:13:13 +00002274//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2275func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002276 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002277 if ethType, ok := classifierInfo[EthType]; ok {
2278 if ethType.(uint32) == IPv4EthType {
2279 if ipProto, ok := classifierInfo[IPProto]; ok {
2280 if ipProto.(uint32) == IgmpProto {
2281 return true
2282 }
2283 }
2284 }
2285 }
2286 }
2287 return false
2288}
2289
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002290// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002291func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002292 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2293 // The device itself is going to be reset as part of deletion. So nothing to be done.
2294 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2295 return nil
2296 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002297 // Step1 : Fill flowControlBlock
2298 // Step2 : Push the flowControlBlock to ONU channel
2299 // Step3 : Wait on response channel for response
2300 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002301 startTime := time.Now()
2302 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002303 errChan := make(chan error)
2304 flowCb := flowControlBlock{
2305 ctx: ctx,
2306 addFlow: addFlow,
2307 flow: flow,
2308 flowMetadata: flowMetadata,
2309 errChan: &errChan,
2310 }
2311 inPort, outPort := getPorts(flow)
2312 var onuID uint32
2313 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002314 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002315 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002316 if f.flowHandlerRoutineActive[onuID] {
2317 // inPort or outPort is InvalidPort for trap-from-nni flows.
2318 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2319 // Send the flowCb on the ONU flow channel
2320 f.incomingFlows[onuID] <- flowCb
2321 // Wait on the channel for flow handlers return value
2322 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002323 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002324 return err
2325 }
2326 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2327 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002328}
2329
2330// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2331// 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 -07002332func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002333 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002334 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002335 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002336 // block on the channel to receive an incoming flow
2337 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002338 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002339 if flowCb.addFlow {
2340 logger.Info(flowCb.ctx, "adding-flow-start")
2341 startTime := time.Now()
2342 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2343 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2344 // Pass the return value over the return channel
2345 *flowCb.errChan <- err
2346 } else {
2347 logger.Info(flowCb.ctx, "removing-flow-start")
2348 startTime := time.Now()
2349 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2350 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2351 // Pass the return value over the return channel
2352 *flowCb.errChan <- err
2353 }
2354 case <-stopHandler:
2355 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2356 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002357 }
2358 }
2359}
2360
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002361// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002362func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002363 for i, v := range f.stopFlowHandlerRoutine {
2364 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002365 select {
2366 case v <- true:
2367 case <-time.After(time.Second * 5):
2368 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2369 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002370 }
2371 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002372 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002373 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2374}
2375
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002376// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302377// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002378func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002379 classifierInfo := make(map[string]interface{})
2380 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002381 var UsMeterID uint32
2382 var DsMeterID uint32
2383
Neha Sharma96b7bf22020-06-15 10:37:32 +00002384 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302385 log.Fields{
2386 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002387 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002388 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002389
Neha Sharma96b7bf22020-06-15 10:37:32 +00002390 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002391 if err != nil {
2392 // Error logging is already done in the called function
2393 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002394 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302395 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002396
Esin Karamanccb714b2019-11-29 15:02:06 +00002397 if flows.HasGroup(flow) {
2398 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002399 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002400 }
2401
manikkaraj k17652a72019-05-06 09:06:36 -04002402 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002403 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002404 if err != nil {
2405 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002406 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002407 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002408
Neha Sharma96b7bf22020-06-15 10:37:32 +00002409 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302410 log.Fields{
2411 "classifierinfo_inport": classifierInfo[InPort],
2412 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002413 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002414
Humera Kouser94d7a842019-08-25 19:04:32 -04002415 if ethType, ok := classifierInfo[EthType]; ok {
2416 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002417 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002418 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002419 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002420 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002421 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002422 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2423 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2424 }
2425 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002426 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002427 if ipProto, ok := classifierInfo[IPProto]; ok {
2428 if ipProto.(uint32) == IPProtoDhcp {
2429 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302430 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002431 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002432 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002433 }
2434 }
2435 }
2436 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002437 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002438 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002439 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002440 }
A R Karthick1f85b802019-10-11 05:06:05 +00002441
npujarec5762e2020-01-01 14:08:48 +05302442 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002443 // also update flowmgr cache
2444 f.onuGemInfoLock.Lock()
2445 onugem, ok := f.onuGemInfoMap[onuID]
2446 if ok {
2447 found := false
2448 for _, uni := range onugem.UniPorts {
2449 if uni == portNo {
2450 found = true
2451 break
2452 }
2453 }
2454 if !found {
2455 onugem.UniPorts = append(onugem.UniPorts, portNo)
2456 f.onuGemInfoMap[onuID] = onugem
2457 logger.Infow(ctx, "added uni port to onugem cache", log.Fields{"uni": portNo})
2458 }
2459 }
2460 f.onuGemInfoLock.Unlock()
A R Karthick1f85b802019-10-11 05:06:05 +00002461
Girish Gowdra6071f382021-12-14 12:52:04 +05302462 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002463 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302464 return olterrors.NewErrNotFound("tpid-for-flow",
2465 log.Fields{
2466 "flow": flow,
2467 "intf-id": IntfID,
2468 "onu-id": onuID,
2469 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002470 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002471 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302472 log.Fields{
Girish Gowdra6071f382021-12-14 12:52:04 +05302473 "tp-id": tpID,
Shrey Baid26912972020-04-16 21:02:31 +05302474 "intf-id": intfID,
2475 "onu-id": onuID,
2476 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002477 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002478 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002479 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302480 if err := f.validateMeter(ctx, Upstream, UsMeterID, intfID, onuID, uniID, tpID); err != nil {
2481 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2482 return err
2483 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002484 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002485 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002486 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302487 if err := f.validateMeter(ctx, Downstream, DsMeterID, intfID, onuID, uniID, tpID); err != nil {
2488 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2489 return err
2490 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002491 }
Girish Gowdra6071f382021-12-14 12:52:04 +05302492 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, tpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002493}
Girish Gowdra3d633032019-12-10 16:37:05 +05302494
Esin Karamanccb714b2019-11-29 15:02:06 +00002495// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002496func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302497 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002498 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302499 "classifier-info": classifierInfo,
2500 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002501
Esin Karaman65409d82020-03-18 10:58:18 +00002502 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002503 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002504 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002505 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002506
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002507 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002508
David K. Bainbridge794735f2020-02-11 21:01:37 -08002509 onuID := NoneOnuID
2510 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002511
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002512 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002513 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002514 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002515 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002516 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2517 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002518 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002519 }
2520 groupID := actionInfo[GroupID].(uint32)
2521 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002522 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002523 FlowType: Multicast,
2524 NetworkIntfId: int32(networkInterfaceID),
2525 GroupId: groupID,
2526 Classifier: classifierProto,
2527 Priority: int32(flow.Priority),
2528 Cookie: flow.Cookie}
2529
Kent Hagermane6ff1012020-07-14 15:07:53 -04002530 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002531 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002532 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002533 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002534 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002535 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002536 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002537 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002538 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002539 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002540 //cached group can be removed now
2541 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002542 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002543 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002544 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002545
David K. Bainbridge794735f2020-02-11 21:01:37 -08002546 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002547}
2548
Esin Karaman65409d82020-03-18 10:58:18 +00002549//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2550func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2551 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002552 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002553 if err != nil {
2554 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2555 }
2556 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002557 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002558
2559 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2560 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002561}
2562
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002563//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002564func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32, tpInst tp_pb.TechProfileInstance) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002565
Neha Sharma96b7bf22020-06-15 10:37:32 +00002566 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302567 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002568 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302569 log.Fields{
2570 "intf-id": intfID,
2571 "onu-id": onuID,
2572 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002573 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302574 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002575 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002576
Neha Sharma96b7bf22020-06-15 10:37:32 +00002577 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002578 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002579 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002580 UniId: uniID,
2581 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002582 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002583 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002584 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002585
2586 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2587 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302588 return olterrors.NewErrCommunication("send-techprofile-download-request",
2589 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002590 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302591 "to-adapter": onuDev.deviceType,
2592 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002593 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002594 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002595 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302596 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302597}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002598
Girish Gowdra197acc12021-08-16 10:59:45 -07002599//AddOnuInfoToFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2600func (f *OpenOltFlowMgr) AddOnuInfoToFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302601
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002602 f.onuGemInfoLock.RLock()
2603 _, ok := f.onuGemInfoMap[onuID]
2604 f.onuGemInfoLock.RUnlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002605 // If the ONU already exists in onuGemInfo list, nothing to do
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002606 if ok {
2607 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2608 log.Fields{"onuID": onuID,
2609 "serialNum": serialNum})
2610 return nil
Girish Gowdra9602eb42020-09-09 15:50:39 -07002611 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002612
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002613 onuGemInfo := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2614 f.onuGemInfoLock.Lock()
2615 f.onuGemInfoMap[onuID] = &onuGemInfo
2616 f.onuGemInfoLock.Unlock()
2617 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onuID, onuGemInfo); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002618 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302619 }
Girish Gowdra197acc12021-08-16 10:59:45 -07002620 logger.Infow(ctx, "added-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302621 log.Fields{
2622 "intf-id": intfID,
2623 "onu-id": onuID,
2624 "serial-num": serialNum,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002625 "onu": onuGemInfo,
Shrey Baid26912972020-04-16 21:02:31 +05302626 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002627 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002628}
2629
Girish Gowdra197acc12021-08-16 10:59:45 -07002630//RemoveOnuInfoFromFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2631func (f *OpenOltFlowMgr) RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32) error {
2632
2633 f.onuGemInfoLock.Lock()
2634 delete(f.onuGemInfoMap, onuID)
2635 f.onuGemInfoLock.Unlock()
2636
2637 if err := f.resourceMgr.DelOnuGemInfo(ctx, intfID, onuID); err != nil {
2638 return err
2639 }
2640 logger.Infow(ctx, "deleted-onuinfo",
2641 log.Fields{
2642 "intf-id": intfID,
2643 "onu-id": onuID,
2644 "device-id": f.deviceHandler.device.Id})
2645 return nil
2646}
2647
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302648//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302649func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002650
Neha Sharma96b7bf22020-06-15 10:37:32 +00002651 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302652 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002653 "gem-port-id": gemPort,
2654 "intf-id": intfID,
2655 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002656 "device-id": f.deviceHandler.device.Id})
2657 f.onuGemInfoLock.RLock()
2658 onugem, ok := f.onuGemInfoMap[onuID]
2659 f.onuGemInfoLock.RUnlock()
2660 if !ok {
2661 logger.Warnw(ctx, "onu gem info is missing", log.Fields{
2662 "gem-port-id": gemPort,
2663 "intf-id": intfID,
2664 "onu-id": onuID,
2665 "device-id": f.deviceHandler.device.Id})
2666 return
2667 }
2668
2669 if onugem.OnuID == onuID {
2670 // check if gem already exists , else update the cache and kvstore
2671 for _, gem := range onugem.GemPorts {
2672 if gem == gemPort {
2673 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2674 log.Fields{
2675 "gem": gemPort,
2676 "device-id": f.deviceHandler.device.Id})
2677 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302678 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302679 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002680 onugem.GemPorts = append(onugem.GemPorts, gemPort)
2681 f.onuGemInfoLock.Lock()
2682 f.onuGemInfoMap[onuID] = onugem
2683 f.onuGemInfoLock.Unlock()
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002684 logger.Debugw(ctx, "updated onu gem info from cache", log.Fields{"onugem": onugem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002685 } else {
2686 logger.Warnw(ctx, "mismatched onu id", log.Fields{
2687 "gem-port-id": gemPort,
2688 "intf-id": intfID,
2689 "onu-id": onuID,
2690 "device-id": f.deviceHandler.device.Id})
2691 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302692 }
npujarec5762e2020-01-01 14:08:48 +05302693 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302694 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002695 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302696 log.Fields{
2697 "intf-id": intfID,
2698 "onu-id": onuID,
2699 "gemPort": gemPort,
2700 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002701 return
2702 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002703 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302704 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002705 "gem-port-id": gemPort,
2706 "intf-id": intfID,
2707 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002708 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002709}
2710
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002711//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302712func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002713 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002714
2715 if packetIn.IntfType == "pon" {
2716 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002717 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002718 onuID, uniID := packetIn.OnuId, packetIn.UniId
2719 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 +00002720
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002721 if packetIn.PortNo != 0 {
2722 logicalPortNum = packetIn.PortNo
2723 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002724 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002725 }
2726 // 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 +00002727 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002728 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002729 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002730 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002731
2732 if logger.V(log.DebugLevel) {
2733 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2734 log.Fields{
2735 "logical-port-num": logicalPortNum,
2736 "intf-type": packetIn.IntfType,
2737 "packet": hex.EncodeToString(packetIn.Pkt),
2738 })
2739 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002740 return logicalPortNum, nil
2741}
2742
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002743//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002744func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002745 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002746
2747 ctag, priority, err := getCTagFromPacket(ctx, packet)
2748 if err != nil {
2749 return 0, err
2750 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302751
Esin Karaman7fb80c22020-07-16 14:23:33 +00002752 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002753 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002754 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002755 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002756 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302757 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002758 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302759 log.Fields{
2760 "pktinkey": pktInkey,
2761 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002762
2763 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002764 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302765 //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 +00002766 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302767 if err == nil {
2768 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002769 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302770 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002771 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002772 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302773 log.Fields{
2774 "pktinkey": pktInkey,
2775 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302776 return gemPortID, nil
2777 }
2778 }
Shrey Baid26912972020-04-16 21:02:31 +05302779 return uint32(0), olterrors.NewErrNotFound("gem-port",
2780 log.Fields{
2781 "pktinkey": pktInkey,
2782 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002783
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002784}
2785
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002786func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2787 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002788 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002789 classifier[PacketTagType] = DoubleTag
2790 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002791 /* We manage flowId resource pool on per PON port basis.
2792 Since this situation is tricky, as a hack, we pass the NNI port
2793 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002794 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002795 on NNI port, use onu_id as -1 (invalid)
2796 ****************** CAVEAT *******************
2797 This logic works if the NNI Port Id falls within the same valid
2798 range of PON Port Ids. If this doesn't work for some OLT Vendor
2799 we need to have a re-look at this.
2800 *********************************************
2801 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002802 onuID := -1
2803 uniID := -1
2804 gemPortID := -1
2805 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002806 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302807 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302808 return olterrors.NewErrNotFound("nni-intreface-id",
2809 log.Fields{
2810 "classifier": classifier,
2811 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002812 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302813 }
2814
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002815 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002816 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002817 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002818 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002819
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002820 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2821 log.Fields{
2822 "classifier": classifier,
2823 "action": action,
2824 "flowId": logicalFlow.Id,
2825 "intf-id": networkInterfaceID})
2826
David K. Bainbridge794735f2020-02-11 21:01:37 -08002827 classifierProto, err := makeOpenOltClassifierField(classifier)
2828 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002829 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002830 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002831 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002832 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002833 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002834 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002835 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002836 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002837 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2838 OnuId: int32(onuID), // OnuId not required
2839 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002840 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002841 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002842 AllocId: int32(allocID), // AllocId not used
2843 NetworkIntfId: int32(networkInterfaceID),
2844 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002845 Classifier: classifierProto,
2846 Action: actionProto,
2847 Priority: int32(logicalFlow.Priority),
2848 Cookie: logicalFlow.Cookie,
2849 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002850 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002851 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002852 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002853 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002854 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002855}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002856
Esin Karamanae41e2b2019-12-17 18:13:13 +00002857//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2858func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2859 var packetType string
2860 ovid, ivid := false, false
2861 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2862 vid := vlanID & VlanvIDMask
2863 if vid != ReservedVlan {
2864 ovid = true
2865 }
2866 }
2867 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2868 vid := uint32(metadata)
2869 if vid != ReservedVlan {
2870 ivid = true
2871 }
2872 }
2873 if ovid && ivid {
2874 packetType = DoubleTag
2875 } else if !ovid && !ivid {
2876 packetType = Untagged
2877 } else {
2878 packetType = SingleTag
2879 }
2880 return packetType
2881}
2882
2883//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002884func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002885 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002886 action := make(map[string]interface{})
2887 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2888 action[TrapToHost] = true
2889 /* We manage flowId resource pool on per PON port basis.
2890 Since this situation is tricky, as a hack, we pass the NNI port
2891 index (network_intf_id) as PON port Index for the flowId resource
2892 pool. Also, there is no ONU Id available for trapping packets
2893 on NNI port, use onu_id as -1 (invalid)
2894 ****************** CAVEAT *******************
2895 This logic works if the NNI Port Id falls within the same valid
2896 range of PON Port Ids. If this doesn't work for some OLT Vendor
2897 we need to have a re-look at this.
2898 *********************************************
2899 */
2900 onuID := -1
2901 uniID := -1
2902 gemPortID := -1
2903 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002904 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002905 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302906 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002907 "classifier": classifier,
2908 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002909 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002910 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002911 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002912 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002913 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002914 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002915
David K. Bainbridge794735f2020-02-11 21:01:37 -08002916 classifierProto, err := makeOpenOltClassifierField(classifier)
2917 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002918 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002919 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002920 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002921 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002922 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002923 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002924 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002925 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002926 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2927 OnuId: int32(onuID), // OnuId not required
2928 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002929 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002930 FlowType: Downstream,
2931 AllocId: int32(allocID), // AllocId not used
2932 NetworkIntfId: int32(networkInterfaceID),
2933 GemportId: int32(gemPortID), // GemportId not used
2934 Classifier: classifierProto,
2935 Action: actionProto,
2936 Priority: int32(logicalFlow.Priority),
2937 Cookie: logicalFlow.Cookie,
2938 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002939 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002940 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002941 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002942 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002943
David K. Bainbridge794735f2020-02-11 21:01:37 -08002944 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002945}
2946
salmansiddiqui7ac62132019-08-22 03:58:50 +00002947func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2948 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302949 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002950 }
2951 if Dir == tp_pb.Direction_UPSTREAM {
2952 return "upstream", nil
2953 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2954 return "downstream", nil
2955 }
2956 return "", nil
2957}
2958
Kent Hagermane6ff1012020-07-14 15:07:53 -04002959// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302960func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002961 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002962 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002963 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002964 intfID := args[IntfID]
2965 onuID := args[OnuID]
2966 uniID := args[UniID]
2967 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002968 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002969 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002970 gemToAes := make(map[uint32]bool)
2971
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002972 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002973 var direction = tp_pb.Direction_UPSTREAM
2974 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002975 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002976 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002977 attributes = TpInst.UpstreamGemPortAttributeList
2978 } else {
2979 attributes = TpInst.DownstreamGemPortAttributeList
2980 direction = tp_pb.Direction_DOWNSTREAM
2981 }
2982 default:
2983 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002984 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002985 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002986
2987 if len(gemPorts) == 1 {
2988 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002989 gemPortID = gemPorts[0]
2990 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002991 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2992 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002993 pBitMap := attributes[idx].PbitMap
2994 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2995 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2996 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002997 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002998 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2999 if pbitSet == pbit1 {
3000 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
3001 pbitToGem[pcp] = gemID
3002 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003003 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003004 }
3005 }
3006 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003007 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
3008 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
3009 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00003010 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003011 }
3012
Gamze Abaka7650be62021-02-26 10:50:36 +00003013 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
3014 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
3015
salmansiddiqui7ac62132019-08-22 03:58:50 +00003016 if ipProto, ok := classifierInfo[IPProto]; ok {
3017 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003018 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003019 "tp-id": tpID,
3020 "alloc-id": allocID,
3021 "intf-id": intfID,
3022 "onu-id": onuID,
3023 "uni-id": uniID,
3024 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003025 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00003026 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003027 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003028 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})
3029 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003030 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00003031 }
3032
Girish Gowdra32625212020-04-29 11:26:35 -07003033 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003034 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05303035 log.Fields{
3036 "intf-id": intfID,
3037 "onu-id": onuID,
3038 "uni-id": uniID,
3039 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00003040 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003041 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003042 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})
3043 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003044 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00003045 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003046 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003047 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003048 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003049 }
3050 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03003051 if ethType.(uint32) == EapEthType {
3052 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003053 "intf-id": intfID,
3054 "onu-id": onuID,
3055 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03003056 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07003057 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003058 var vlanID uint32
3059 if val, ok := classifierInfo[VlanVid]; ok {
3060 vlanID = (val.(uint32)) & VlanvIDMask
3061 } else {
3062 vlanID = DefaultMgmtVlan
3063 }
Gamze Abaka7650be62021-02-26 10:50:36 +00003064 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003065 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003066 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})
3067 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003068 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00003069 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03003070 } else if ethType.(uint32) == PPPoEDEthType {
3071 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
3072 "tp-id": tpID,
3073 "alloc-id": allocID,
3074 "intf-id": intfID,
3075 "onu-id": onuID,
3076 "uni-id": uniID,
3077 })
3078 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00003079 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03003080 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003081 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})
3082 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003083 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03003084 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003085 }
Gamze Abaka7650be62021-02-26 10:50:36 +00003086 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003087 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003088 "intf-id": intfID,
3089 "onu-id": onuID,
3090 "uni-id": uniID,
3091 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003092 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00003093 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003094 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003095 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})
3096 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003097 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00003098 }
Gamze Abaka7650be62021-02-26 10:50:36 +00003099 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003100 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003101 "intf-id": intfID,
3102 "onu-id": onuID,
3103 "uni-id": uniID,
3104 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003105 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00003106 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003107 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003108 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})
3109 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003110 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00003111 }
3112 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003113 return olterrors.NewErrInvalidValue(log.Fields{
3114 "intf-id": intfID,
3115 "onu-id": onuID,
3116 "uni-id": uniID,
3117 "classifier": classifierInfo,
3118 "action": actionInfo,
3119 "flow": flow},
3120 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003121 }
3122 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04003123 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003124 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003125 logger.Warn(ctx, err)
3126 }
3127 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003128 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00003129}
3130
Gamze Abaka745ccb72021-11-18 11:29:58 +00003131func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32, flowID uint64) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003132 f.gemToFlowIDsKey.RLock()
3133 flowIDList := f.gemToFlowIDs[gemPortID]
3134 f.gemToFlowIDsKey.RUnlock()
Gamze Abaka745ccb72021-11-18 11:29:58 +00003135 if len(flowIDList) > 0 {
3136 for _, id := range flowIDList {
3137 if flowID != id {
3138 return true
Gamze Abakafee36392019-10-03 11:17:24 +00003139 }
3140 }
3141 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00003142 return false
Gamze Abakacb0e6772021-06-10 08:32:12 +00003143}
Girish Gowdra54934262019-11-13 14:19:55 +05303144
Gamze Abakacb0e6772021-06-10 08:32:12 +00003145func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003146 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
3147 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
3148 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 +05303149 for i := 0; i < len(tpInstances); i++ {
3150 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00003151 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003152 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Girish Gowdraf3728b12022-02-02 21:46:51 -08003153 logger.Debugw(ctx, "alloc-is-in-use-on-another-uni",
Gamze Abakacb0e6772021-06-10 08:32:12 +00003154 log.Fields{
3155 "device-id": f.deviceHandler.device.Id,
3156 "intfID": sq.intfID,
3157 "onuID": sq.onuID,
3158 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003159 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00003160 })
3161 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303162 }
3163 }
3164 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003165 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003166}
3167
Neha Sharma96b7bf22020-06-15 10:37:32 +00003168func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003169 for _, field := range flows.GetOfbFields(flow) {
3170 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003171 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003172 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003173 } else if field.Type == flows.ETH_DST {
3174 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003175 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003176 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003177 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003178 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003179 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003180 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003181 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003182 } else if field.Type == flows.VLAN_VID {
Andrea Campanellafaa42152021-10-28 11:50:56 +05303183 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3184 if field.GetVlanVid() != ReservedVlan {
3185 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3186 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3187 }
Scott Baker355d1742019-10-24 10:57:52 -07003188 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003189 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003190 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003191 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003192 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003193 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003194 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003195 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003196 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003197 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003198 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003199 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003200 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003201 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003202 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003203 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003204 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003205 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003206 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003207 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003208 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003209 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003210 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003211 return
3212 }
3213 }
3214}
3215
Neha Sharma96b7bf22020-06-15 10:37:32 +00003216func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003217 for _, action := range flows.GetActions(flow) {
3218 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003219 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003220 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003221 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003222 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003223 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003224 }
Scott Baker355d1742019-10-24 10:57:52 -07003225 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003226 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003227 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003228 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003229 if out := action.GetPush(); out != nil {
3230 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003231 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003232 } else {
3233 actionInfo[PushVlan] = true
3234 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003235 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303236 log.Fields{
3237 "push-tpid": actionInfo[TPID].(uint32),
3238 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003239 }
3240 }
Scott Baker355d1742019-10-24 10:57:52 -07003241 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003242 if out := action.GetSetField(); out != nil {
3243 if field := out.GetField(); field != nil {
3244 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003245 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003246 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003247 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3248 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003249 }
3250 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003251 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003252 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003253 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003254 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003255 }
3256 }
3257 return nil
3258}
3259
Neha Sharma96b7bf22020-06-15 10:37:32 +00003260func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003261 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003262 fieldtype := ofbField.GetType()
3263 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003264 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3265 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003266 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003267 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003268 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003269 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003270 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3271 pcp := ofbField.GetVlanPcp()
3272 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003273 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003274 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003275 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003276 }
3277 }
3278}
3279
Neha Sharma96b7bf22020-06-15 10:37:32 +00003280func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003281 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003282 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003283 } else {
3284 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003285 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003286 }
3287}
3288
Neha Sharma96b7bf22020-06-15 10:37:32 +00003289func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003290 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003291 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003292 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003293 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003294 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003295 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003296 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303297 log.Fields{
3298 "newinport": classifierInfo[InPort].(uint32),
3299 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003300 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303301 return olterrors.NewErrNotFound("child-in-port",
3302 log.Fields{
3303 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3304 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003305 }
3306 }
3307 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003308 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003309 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003310 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003311 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003312 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003313 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303314 log.Fields{
3315 "newoutport": actionInfo[Output].(uint32),
3316 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003317 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303318 return olterrors.NewErrNotFound("out-port",
3319 log.Fields{
3320 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3321 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003322 }
3323 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003324 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003325 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003326 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003327 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303328 log.Fields{
3329 "newinport": actionInfo[Output].(uint32),
3330 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003331 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303332 return olterrors.NewErrNotFound("nni-port",
3333 log.Fields{
3334 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3335 "in-port": classifierInfo[InPort].(uint32),
3336 "out-port": actionInfo[Output].(uint32),
3337 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003338 }
3339 }
3340 }
3341 return nil
3342}
Gamze Abakafee36392019-10-03 11:17:24 +00003343
Neha Sharma96b7bf22020-06-15 10:37:32 +00003344func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003345 /* Metadata 8 bytes:
3346 Most Significant 2 Bytes = Inner VLAN
3347 Next 2 Bytes = Tech Profile ID(TPID)
3348 Least Significant 4 Bytes = Port ID
3349 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3350 subscriber related flows.
3351 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003352 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003353 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003354 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003355 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003356 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003357 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003358}
3359
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003360func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3361 for _, sliceElement := range slice {
3362 if sliceElement == item {
3363 return slice
3364 }
3365 }
3366 return append(slice, item)
3367}
3368
3369func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003370 for _, sliceElement := range slice {
3371 if sliceElement == item {
3372 return slice
3373 }
3374 }
3375 return append(slice, item)
3376}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303377
3378// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003379func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303380
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003381 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303382 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003383 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003384 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003385 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003386 log.Fields{
3387 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003388 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003389 return uint32(0), err
3390 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003391 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303392 return intfID, nil
3393 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003394 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003395 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003396 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003397 log.Fields{
3398 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003399 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003400 return uint32(0), err
3401 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003402 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303403 return intfID, nil
3404 }
3405 return uint32(0), nil
3406}
3407
3408// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003409func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3410 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3411 if err != nil {
3412 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3413 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3414 return
3415 }
3416 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003417
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003418 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003419 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003420 f.packetInGemPortLock.RUnlock()
3421
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303422 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003423 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003424 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 +05303425 log.Fields{
3426 "pktinkey": pktInkey,
3427 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003428 return
3429 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303430 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003431 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003432 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003433 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003434
npujarec5762e2020-01-01 14:08:48 +05303435 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003436 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 +05303437 log.Fields{
3438 "pktinkey": pktInkey,
3439 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303440}
3441
Esin Karaman7fb80c22020-07-16 14:23:33 +00003442//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3443func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3444 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003445 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003446 return 0, 0, errors.New("invalid packet length")
3447 }
3448 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3449 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3450
3451 var index int8
3452 if outerEthType == 0x8100 {
3453 if innerEthType == 0x8100 {
3454 // q-in-q 802.1ad or 802.1q double tagged packet.
3455 // get the inner vlanId
3456 index = 18
3457 } else {
3458 index = 14
3459 }
3460 priority := (packet[index] >> 5) & 0x7
3461 //13 bits composes vlanId value
3462 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3463 return vlan, priority, nil
3464 }
3465 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3466 return 0, 0, nil
3467}
3468
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003469func (f *OpenOltFlowMgr) loadFlowIDsForGemAndGemIDsForFlow(ctx context.Context) {
3470 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - start")
3471 f.onuGemInfoLock.RLock()
3472 f.gemToFlowIDsKey.Lock()
3473 f.flowIDToGemsLock.Lock()
3474 for _, og := range f.onuGemInfoMap {
3475 for _, gem := range og.GemPorts {
3476 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, f.ponPortIdx, gem)
Gamze Abaka6f345c12021-09-08 01:14:33 +00003477 if err == nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003478 f.gemToFlowIDs[gem] = flowIDs
3479 for _, flowID := range flowIDs {
3480 if _, ok := f.flowIDToGems[flowID]; !ok {
3481 f.flowIDToGems[flowID] = []uint32{gem}
3482 } else {
3483 f.flowIDToGems[flowID] = appendUnique32bit(f.flowIDToGems[flowID], gem)
3484 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303485 }
3486 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303487 }
3488 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003489 f.flowIDToGemsLock.Unlock()
3490 f.gemToFlowIDsKey.Unlock()
3491 f.onuGemInfoLock.RUnlock()
3492 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - end")
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303493}
Esin Karamanccb714b2019-11-29 15:02:06 +00003494
Girish Gowdra9602eb42020-09-09 15:50:39 -07003495//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3496// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003497func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003498 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003499 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3500 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003501 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003502 "flow-id": flow.Id,
3503 "device-id": f.deviceHandler.device.Id})
3504 // Remove from device
3505 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3506 // DKB
3507 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3508 log.Fields{
3509 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003510 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003511 return err
3512 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003513
3514 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003515}
3516
khenaidoodc2116e2021-10-19 17:33:19 -04003517func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003518 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003519 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003520 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003521 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003522 }
3523
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003524 switch tpInst := tpInst.(type) {
3525 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003526 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003527 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003528 DeviceId: onuDeviceID,
3529 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003530 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003531 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003532 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003533 case *tp_pb.EponTechProfileInstance:
3534 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003535 DeviceId: onuDeviceID,
3536 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003537 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003538 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003539 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003540 default:
3541 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003542 }
khenaidoodc2116e2021-10-19 17:33:19 -04003543 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003544 DeviceId: onuDeviceID,
3545 UniId: uniID,
3546 TpInstancePath: tpPath,
3547 TechTpInstance: nil,
3548 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003549}
3550
Girish Gowdrabcf98af2021-07-01 08:24:42 -07003551func (f *OpenOltFlowMgr) getOnuGemInfoList(ctx context.Context) []rsrcMgr.OnuGemInfo {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003552 var onuGemInfoLst []rsrcMgr.OnuGemInfo
3553 f.onuGemInfoLock.RLock()
3554 defer f.onuGemInfoLock.RUnlock()
3555 for _, v := range f.onuGemInfoMap {
3556 onuGemInfoLst = append(onuGemInfoLst, *v)
3557 }
3558 return onuGemInfoLst
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003559}
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003560
3561// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3562func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
3563
3564 intfID := sq.intfID
3565 onuID := sq.onuID
3566 uniID := sq.uniID
3567 tpID := sq.tpID
3568
3569 var reverseDirection string
3570 if sq.direction == tp_pb.Direction_UPSTREAM {
3571 reverseDirection = "downstream"
3572 } else {
3573 reverseDirection = "upstream"
3574 }
3575
3576 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
3577 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, intfID, onuID, uniID, tpID); KvStoreMeter != nil {
3578 return
3579 }
3580
3581 // revert-delete tech-profile instance and delete tech profile id for onu
3582 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})
3583 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3584 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
3585 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, onuID, uniID, tpID)
3586
3587 // free gem/alloc
3588 switch techprofileInst := sq.tpInst.(type) {
3589 case *tp_pb.TechProfileInstance:
3590 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
3591 f.resourceMgr.FreeGemPortID(ctx, intfID, onuID, uniID, gem.GemportId)
3592 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08003593 f.resourceMgr.FreeAllocID(ctx, intfID, onuID, uniID, techprofileInst.UsScheduler.AllocId, true)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003594 }
3595}
3596
3597// revertSchduler is called when CreateQueues request fails
3598func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3599 // revert scheduler
3600 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})
3601 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
3602 IntfId: sq.intfID, OnuId: sq.onuID,
3603 UniId: sq.uniID, PortNo: sq.uniPort,
3604 TrafficScheds: TrafficSched})
3605}
Girish Gowdra6071f382021-12-14 12:52:04 +05303606
3607// validateMeter validates if there is a meter mismatch for the given direction. It also clears the stale meter if the reference count is zero
3608func (f *OpenOltFlowMgr) validateMeter(ctx context.Context, direction string, meterID uint32, intfID uint32, onuID uint32, uniID uint32, tpID uint32) error {
3609 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, intfID, onuID, uniID, tpID)
3610 if err != nil {
3611 return olterrors.NewErrNotFound("meter",
3612 log.Fields{"intf-id": intfID,
3613 "onu-id": onuID,
3614 "uni-id": uniID,
3615 "device-id": f.deviceHandler.device.Id}, err)
3616 }
3617
3618 if meterInfo != nil {
3619 // If RefCnt become 0 clear the meter information from the DB.
3620 if meterInfo.MeterID != meterID && meterInfo.RefCnt == 0 {
3621 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, intfID, onuID, uniID, tpID); err != nil {
3622 return err
3623 }
3624 } else if meterInfo.MeterID != meterID {
3625 logger.Errorw(ctx, "meter-mismatch-for-direction",
3626 log.Fields{"direction": direction,
3627 "kv-store-meter-id": meterInfo.MeterID,
3628 "meter-id-in-flow": meterID,
3629 "device-id": f.deviceHandler.device.Id})
3630 return olterrors.NewErrInvalidValue(log.Fields{
3631 "unsupported": "meter-id",
3632 "kv-store-meter-id": meterInfo.MeterID,
3633 "meter-id-in-flow": meterID,
3634 "device-id": f.deviceHandler.device.Id}, nil)
3635 }
3636 }
3637 return nil
3638}
Girish Gowdraf3728b12022-02-02 21:46:51 -08003639
3640func (f *OpenOltFlowMgr) removeMeterReference(ctx context.Context, direction string, sq schedQueue) error {
3641 /* After we successfully remove the scheduler configuration on the OLT device,
3642 * delete the meter id on the KV store.
3643 */
3644 err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
3645 if err != nil {
3646 return olterrors.NewErrAdapter("unable-to-remove-meter",
3647 log.Fields{
3648 "onu": sq.onuID,
3649 "device-id": f.deviceHandler.device.Id,
3650 "intf-id": sq.intfID,
3651 "onu-id": sq.onuID,
3652 "uni-id": sq.uniID,
3653 "uni-port": sq.uniPort}, err)
3654 }
3655 logger.Debugw(ctx, "removed-meter-from-KV-store-successfully",
3656 log.Fields{
3657 "dir": direction,
3658 "device-id": f.deviceHandler.device.Id,
3659 "intf-id": sq.intfID,
3660 "onu-id": sq.onuID,
3661 "uni-id": sq.uniID,
3662 "uni-port": sq.uniPort})
3663 return err
3664}