blob: 61da77db2333623b75c4df4c0600be9cc9281b5b [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
Mahir Gunyel199570a2021-07-04 15:39:36 -070030 "github.com/opencord/voltha-lib-go/v6/pkg/meters"
31
Girish Gowdra4c3d4602021-07-22 16:33:37 -070032 "github.com/opencord/voltha-lib-go/v6/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v6/pkg/log"
34 tp "github.com/opencord/voltha-lib-go/v6/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080035 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070036 "github.com/opencord/voltha-protos/v4/go/common"
37 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
38 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
39 openoltpb2 "github.com/opencord/voltha-protos/v4/go/openolt"
40 tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
41 "github.com/opencord/voltha-protos/v4/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040042
Thomas Lee S94109f12020-03-03 16:39:29 +053043 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000044 "google.golang.org/grpc/codes"
45 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053046)
47
48const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070049 //IPProtoDhcp flow category
50 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053051
Girish Gowdraa09aeab2020-09-14 16:30:52 -070052 //IgmpProto proto value
53 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070054
55 //EapEthType eapethtype value
56 EapEthType = 0x888e
57 //LldpEthType lldp ethtype value
58 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000059 //IPv4EthType IPv4 ethernet type value
60 IPv4EthType = 0x800
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030061 //PPPoEDEthType PPPoE discovery ethernet type value
62 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070063
Andrea Campanella7acc0b92020-02-14 09:20:49 +010064 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
65 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040066
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070067 //DefaultMgmtVlan default vlan value
68 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053069
manikkaraj kbf256be2019-03-25 00:13:48 +053070 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070071
David K. Bainbridge82efc492019-09-04 09:57:11 -070072 //Upstream constant
73 Upstream = "upstream"
74 //Downstream constant
75 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000076 //Multicast constant
77 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070078 //PacketTagType constant
79 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070080 //Untagged constant
81 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070082 //SingleTag constant
83 SingleTag = "single_tag"
84 //DoubleTag constant
85 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053086
87 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070088
89 //EthType constant
90 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000091 //EthDst constant
92 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070093 //TPID constant
94 TPID = "tpid"
95 //IPProto constant
96 IPProto = "ip_proto"
97 //InPort constant
98 InPort = "in_port"
99 //VlanVid constant
100 VlanVid = "vlan_vid"
101 //VlanPcp constant
102 VlanPcp = "vlan_pcp"
103
104 //UDPDst constant
105 UDPDst = "udp_dst"
106 //UDPSrc constant
107 UDPSrc = "udp_src"
108 //Ipv4Dst constant
109 Ipv4Dst = "ipv4_dst"
110 //Ipv4Src constant
111 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700112 //Metadata constant
113 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 //TunnelID constant
115 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700116 //Output constant
117 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000118 //GroupID constant
119 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700120 // Actions
121
122 //PopVlan constant
123 PopVlan = "pop_vlan"
124 //PushVlan constant
125 PushVlan = "push_vlan"
126 //TrapToHost constant
127 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400128 //MaxMeterBand constant
129 MaxMeterBand = 2
130 //VlanPCPMask contant
131 VlanPCPMask = 0xFF
132 //VlanvIDMask constant
133 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000134 //IntfID constant
135 IntfID = "intfId"
136 //OnuID constant
137 OnuID = "onuId"
138 //UniID constant
139 UniID = "uniId"
140 //PortNo constant
141 PortNo = "portNo"
142 //AllocID constant
143 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000144 //GemID constant
145 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000146
147 //NoneOnuID constant
148 NoneOnuID = -1
149 //NoneUniID constant
150 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700151
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700152 // Max number of flows that can be queued per ONU
153 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530154
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700155 bitMapPrefix = "0b"
156 pbit1 = '1'
157)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400158
Gamze Abakafee36392019-10-03 11:17:24 +0000159type schedQueue struct {
160 direction tp_pb.Direction
161 intfID uint32
162 onuID uint32
163 uniID uint32
164 tpID uint32
165 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700166 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000167 meterID uint32
168 flowMetadata *voltha.FlowMetadata
169}
170
Gamze Abaka7650be62021-02-26 10:50:36 +0000171type flowContext struct {
172 intfID uint32
173 onuID uint32
174 uniID uint32
175 portNo uint32
176 classifier map[string]interface{}
177 action map[string]interface{}
178 logicalFlow *ofp.OfpFlowStats
179 allocID uint32
180 gemPortID uint32
181 tpID uint32
182 pbitToGem map[uint32]uint32
183 gemToAes map[uint32]bool
184}
185
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700186// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
187// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
188// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
189// flow and processes it serially
190type flowControlBlock struct {
191 ctx context.Context // Flow handler context
192 addFlow bool // if true flow to be added, else removed
193 flow *voltha.OfpFlowStats // Flow message
194 flowMetadata *voltha.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
195 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000196}
197
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700198//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530199type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700200 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700201 techprofile tp.TechProfileIf
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700202 deviceHandler *DeviceHandler
203 grpMgr *OpenOltGroupMgr
204 resourceMgr *rsrcMgr.OpenOltResourceMgr
205
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700206 gemToFlowIDs map[uint32][]uint64 // gem port id to flow ids
207 gemToFlowIDsKey sync.RWMutex // lock to be used to access the gemToFlowIDs map
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700208
209 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
210 packetInGemPortLock sync.RWMutex
211
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700212 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700213 onuGemInfoMap map[uint32]*rsrcMgr.OnuGemInfo //onu, gem and uni info local cache -> map of onuID to OnuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700214 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700215 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700216
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700217 flowIDToGems map[uint64][]uint32
218 flowIDToGemsLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700219
220 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
221 // 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 -0700222 incomingFlows []chan flowControlBlock
223 stopFlowHandlerRoutine []chan bool
224 flowHandlerRoutineActive []bool
manikkaraj kbf256be2019-03-25 00:13:48 +0530225}
226
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700227//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700228func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000229 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530230 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530231 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530232
manikkaraj kbf256be2019-03-25 00:13:48 +0530233 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700234 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700235 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530236 flowMgr.resourceMgr = rMgr
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700237 if err = flowMgr.populateTechProfileForCurrentPonPort(ctx); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700238 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530239 return nil
240 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700241 flowMgr.gemToFlowIDs = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530242 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700243 flowMgr.flowIDToGems = make(map[uint64][]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700244
245 // Create a slice of buffered channels for handling concurrent flows per ONU.
246 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
247 flowMgr.incomingFlows = make([]chan flowControlBlock, MaxOnusPerPon+1)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700248 flowMgr.stopFlowHandlerRoutine = make([]chan bool, MaxOnusPerPon+1)
249 flowMgr.flowHandlerRoutineActive = make([]bool, MaxOnusPerPon+1)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700250 for i := range flowMgr.incomingFlows {
251 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700252 flowMgr.stopFlowHandlerRoutine[i] = make(chan bool, 1)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700253 // Spin up a go routine to handling incoming flows (add/remove).
254 // There will be on go routine per ONU.
255 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700256 flowMgr.flowHandlerRoutineActive[i] = true
257 go flowMgr.perOnuFlowHandlerRoutine(i, flowMgr.incomingFlows[i], flowMgr.stopFlowHandlerRoutine[i])
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700258 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700259 flowMgr.onuGemInfoMap = make(map[uint32]*rsrcMgr.OnuGemInfo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530260 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700261 onuIDStart := flowMgr.deviceHandler.deviceInfo.OnuIdStart
262 onuIDEnd := flowMgr.deviceHandler.deviceInfo.OnuIdEnd
263 for onuID := onuIDStart; onuID <= onuIDEnd; onuID++ {
264 // check for a valid serial number in onuGem as GetOnuGemInfo can return nil error in case of nothing found in the path.
265 onugem, err := rMgr.GetOnuGemInfo(ctx, onuID, ponPortIdx)
266 if err == nil && onugem != nil && onugem.SerialNumber != "" {
267 flowMgr.onuGemInfoMap[onuID] = onugem
268 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530269 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700270
271 //Load flowID list per gem map And gemIDs per flow per interface from the kvstore.
272 flowMgr.loadFlowIDsForGemAndGemIDsForFlow(ctx)
273
Esin Karamanccb714b2019-11-29 15:02:06 +0000274 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700275 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000276 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530277 return &flowMgr
278}
279
Kent Hagermane6ff1012020-07-14 15:07:53 -0400280func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700281 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
282 // 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 -0700283 return f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700284 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
285 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
286 for _, gemPort := range deviceFlow.PbitToGemport {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700287 if err := f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700288 return err
289 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700290 }
Gamze Abakafee36392019-10-03 11:17:24 +0000291 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700292 return nil
293}
294
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700295func (f *OpenOltFlowMgr) registerFlowIDForGemAndGemIDForFlow(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
296 // update gem->flows map
297 f.gemToFlowIDsKey.Lock()
298 flowIDList, ok := f.gemToFlowIDs[gemPortID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700299 if !ok {
300 flowIDList = []uint64{flowFromCore.Id}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700301 } else {
302 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700303 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700304 f.gemToFlowIDs[gemPortID] = flowIDList
305 f.gemToFlowIDsKey.Unlock()
306
307 // update flow->gems map
308 f.flowIDToGemsLock.Lock()
309 if _, ok := f.flowIDToGems[flowFromCore.Id]; !ok {
310 f.flowIDToGems[flowFromCore.Id] = []uint32{gemPortID}
311 } else {
312 f.flowIDToGems[flowFromCore.Id] = appendUnique32bit(f.flowIDToGems[flowFromCore.Id], gemPortID)
313 }
314 f.flowIDToGemsLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700315
316 // update the flowids for a gem to the KVstore
317 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400318}
319
Girish Gowdra9602eb42020-09-09 15:50:39 -0700320func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000321 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200322 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000323 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530324 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700325 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530326
Neha Sharma96b7bf22020-06-15 10:37:32 +0000327 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530328 "device-id": f.deviceHandler.device.Id,
329 "intf-id": intfID,
330 "onu-id": onuID,
331 "uni-id": uniID,
332 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700333 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530334 "action": actionInfo,
335 "usmeter-iD": UsMeterID,
336 "dsmeter-iD": DsMeterID,
337 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400338 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
339 // is because the flow is an NNI flow and there would be no onu resources associated with it
340 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400341 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200342 cause := "no-onu-id-for-flow"
343 fields := log.Fields{
344 "onu": onuID,
345 "port-no": portNo,
346 "classifer": classifierInfo,
347 "action": actionInfo,
348 "device-id": f.deviceHandler.device.Id}
349 logger.Errorw(ctx, cause, fields)
350 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530351 }
352
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700353 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000354 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530355 "uni": uni,
356 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530357
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700358 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
359 "device-id": f.deviceHandler.device.Id,
360 "intf-id": intfID,
361 "onu-id": onuID,
362 "uni-id": uniID,
363 "port-no": portNo,
364 "classifier": classifierInfo,
365 "action": actionInfo,
366 "usmeter-id": UsMeterID,
367 "dsmeter-id": DsMeterID,
368 "tp-id": TpID})
369 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
370 if allocID == 0 || gemPorts == nil || TpInst == nil {
371 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
372 return olterrors.NewErrNotFound(
373 "alloc-id-gem-ports-tp-unavailable",
374 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400375 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700376 args := make(map[string]uint32)
377 args[IntfID] = intfID
378 args[OnuID] = onuID
379 args[UniID] = uniID
380 args[PortNo] = portNo
381 args[AllocID] = allocID
382
383 /* Flows can be added specific to gemport if p-bits are received.
384 * If no pbit mentioned then adding flows for all gemports
385 */
386 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
387
Andrea Campanellabfe08432020-09-11 17:07:03 +0200388 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530389}
390
salmansiddiqui7ac62132019-08-22 03:58:50 +0000391// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530392func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400393
Neha Sharma96b7bf22020-06-15 10:37:32 +0000394 logger.Debugw(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
Gamze Abakafee36392019-10-03 11:17:24 +0000405 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
410 /* Lets make a simple assumption that if the meter-id is present on the KV store,
411 * then the scheduler and queues configuration is applied on the OLT device
412 * in the given direction.
413 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000414
Manikkaraj kb1d51442019-07-23 10:41:02 -0400415 var SchedCfg *tp_pb.SchedulerConfig
Girish Gowdraa482f272021-03-24 23:04:19 -0700416 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400417 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530418 return olterrors.NewErrNotFound("meter",
419 log.Fields{"intf-id": sq.intfID,
420 "onu-id": sq.onuID,
421 "uni-id": sq.uniID,
422 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400423 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000424
Girish Gowdraa482f272021-03-24 23:04:19 -0700425 if meterInfo != nil {
426 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id, "meter-id": sq.meterID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700427 if meterInfo.MeterID == sq.meterID {
Girish Gowdraa482f272021-03-24 23:04:19 -0700428 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
429 return err
430 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400431 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530433 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800434 "unsupported": "meter-id",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700435 "kv-store-meter-id": meterInfo.MeterID,
Shrey Baid26912972020-04-16 21:02:31 +0530436 "meter-id-in-flow": sq.meterID,
437 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400438 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000439
Neha Sharma96b7bf22020-06-15 10:37:32 +0000440 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530441 log.Fields{
442 "meter-id": sq.meterID,
443 "direction": Direction,
444 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000445
Gamze Abakafee36392019-10-03 11:17:24 +0000446 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700447 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Gamze Abakafee36392019-10-03 11:17:24 +0000448 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700449 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Girish Kumar8f73fe02019-12-09 13:19:37 +0000450 }
451
Girish Gowdraa482f272021-03-24 23:04:19 -0700452 found := false
453 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000454 if sq.flowMetadata != nil {
455 for _, meter := range sq.flowMetadata.Meters {
456 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700457 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700458 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 +0000459 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700460 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530461 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700462 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400463 break
464 }
465 }
466 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000467 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400468 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700469 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530470 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800471 "reason": "Could-not-get-meterbands-from-flowMetadata",
472 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530473 "meter-id": sq.meterID,
474 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400475 }
Gamze Abaka01174422021-03-10 06:55:27 +0000476
477 var TrafficShaping *tp_pb.TrafficShapingInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700478 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
Gamze Abaka01174422021-03-10 06:55:27 +0000479 return olterrors.NewErrInvalidValue(log.Fields{
480 "reason": "invalid-meter-config",
481 "meter-id": sq.meterID,
482 "device-id": f.deviceHandler.device.Id}, nil)
483 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400484
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700485 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000486 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400487
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700488 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530489 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
490 log.Fields{"intf-id": sq.intfID,
491 "direction": sq.direction,
492 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400493 }
494
salmansiddiqui7ac62132019-08-22 03:58:50 +0000495 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400496 * store the meter id on the KV store, for further reference.
497 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700498 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 +0530499 return olterrors.NewErrAdapter("failed-updating-meter-id",
500 log.Fields{"onu-id": sq.onuID,
501 "meter-id": sq.meterID,
502 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000504 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530505 log.Fields{"direction": Direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700506 "meter-info": meterInfo,
507 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400508 return nil
509}
510
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700511func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700512 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000513
514 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530515 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
516 log.Fields{"intf-id": sq.intfID,
517 "direction": sq.direction,
518 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000519 }
520
Gamze Abakacb0e6772021-06-10 08:32:12 +0000521 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
522 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
523 log.Fields{
524 "direction": sq.direction,
525 "TrafficScheds": TrafficSched,
526 "device-id": f.deviceHandler.device.Id,
527 "intfID": sq.intfID,
528 "onuID": sq.onuID,
529 "uniID": sq.uniID})
530 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
531 IntfId: sq.intfID, OnuId: sq.onuID,
532 UniId: sq.uniID, PortNo: sq.uniPort,
533 TrafficScheds: TrafficSched}); err != nil {
534 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
535 }
536 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
537 "direction": sq.direction,
538 "traffic-queues": trafficQueues,
539 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000540 }
541
542 // On receiving the CreateTrafficQueues request, the driver should create corresponding
543 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000544 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530545 log.Fields{"direction": sq.direction,
546 "traffic-queues": trafficQueues,
547 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530548 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000549 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
550 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000551 TrafficQueues: trafficQueues,
552 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530553 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000554 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000555 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530556 "direction": sq.direction,
557 "traffic-queues": trafficQueues,
558 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000559
Esin Karamanccb714b2019-11-29 15:02:06 +0000560 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700561 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000562 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700563 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 +0000564 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
565 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000566 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000567 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700568 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000569 gemPortID: multicastQueuePerPonPort.GemportId,
570 servicePriority: multicastQueuePerPonPort.Priority,
571 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700572 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000573 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400574 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700575 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400576 return err
577 }
Shrey Baid26912972020-04-16 21:02:31 +0530578
Neha Sharma96b7bf22020-06-15 10:37:32 +0000579 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000580 }
581 }
582 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000583 return nil
584}
585
salmansiddiqui7ac62132019-08-22 03:58:50 +0000586// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530587func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400588
589 var Direction string
590 var SchedCfg *tp_pb.SchedulerConfig
591 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000592 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530593 log.Fields{
594 "direction": sq.direction,
595 "intf-id": sq.intfID,
596 "onu-id": sq.onuID,
597 "uni-id": sq.uniID,
598 "uni-port": sq.uniPort,
599 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000600 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700601 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400602 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000603 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700604 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400605 Direction = "downstream"
606 }
607
Girish Gowdraa482f272021-03-24 23:04:19 -0700608 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 -0400609
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700610 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000611 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000612
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700613 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000614 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530615 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
616 log.Fields{
617 "intf-id": sq.intfID,
618 "direction": sq.direction,
619 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000620 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400621
npujarec5762e2020-01-01 14:08:48 +0530622 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000623 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
624 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000625 TrafficQueues: TrafficQueues,
626 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000627 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530628 log.Fields{
629 "intf-id": sq.intfID,
630 "traffic-queues": TrafficQueues,
631 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400632 }
Gamze Abakacb0e6772021-06-10 08:32:12 +0000633 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400634
Gamze Abakacb0e6772021-06-10 08:32:12 +0000635 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
636 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
637 IntfId: sq.intfID, OnuId: sq.onuID,
638 UniId: sq.uniID, PortNo: sq.uniPort,
639 TrafficScheds: TrafficSched}); err != nil {
640 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
641 log.Fields{
642 "intf-id": sq.intfID,
643 "traffic-schedulers": TrafficSched,
644 "onu-id": sq.onuID,
645 "uni-id": sq.uniID,
646 "uni-port": sq.uniPort}, err)
647 }
648
649 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
650 log.Fields{"device-id": f.deviceHandler.device.Id,
651 "intf-id": sq.intfID,
652 "onu-id": sq.onuID,
653 "uni-id": sq.uniID,
654 "uni-port": sq.uniPort})
655
656 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700657 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
Gamze Abakacb0e6772021-06-10 08:32:12 +0000658 f.resourceMgr.FreeAllocID(ctx, sq.intfID, sq.onuID, sq.uniID, allocID)
659 // Delete the TCONT on the ONU.
660 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
661 tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
662 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
663 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
664 log.Fields{
665 "intf": sq.intfID,
666 "onu-id": sq.onuID,
667 "uni-id": sq.uniID,
668 "device-id": f.deviceHandler.device.Id,
669 "alloc-id": allocID})
670 }
671 }
672 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000673
674 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400675 * delete the meter id on the KV store.
676 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700677 err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400678 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530679 return olterrors.NewErrAdapter("unable-to-remove-meter",
680 log.Fields{
681 "onu": sq.onuID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700682 "device-id": f.deviceHandler.device.Id,
683 "intf-id": sq.intfID,
684 "onu-id": sq.onuID,
685 "uni-id": sq.uniID,
686 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400687 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000688 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530689 log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530690 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700691 "device-id": f.deviceHandler.device.Id,
692 "intf-id": sq.intfID,
693 "onu-id": sq.onuID,
694 "uni-id": sq.uniID,
695 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400696 return err
697}
698
Girish Gowdra197acc12021-08-16 10:59:45 -0700699// We are trying to force remove the schedulers and queues here if one exists for the given key.
700// We ignore any errors encountered in the process. The errors most likely are encountered when
701// the schedulers and queues are already cleared for the given key.
702func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
703
704 var schedCfg *tp_pb.SchedulerConfig
705 var err error
706 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
707 log.Fields{
708 "direction": sq.direction,
709 "intf-id": sq.intfID,
710 "onu-id": sq.onuID,
711 "uni-id": sq.uniID,
712 "uni-port": sq.uniPort,
713 "tp-id": sq.tpID,
714 "device-id": f.deviceHandler.device.Id})
715 if sq.direction == tp_pb.Direction_UPSTREAM {
716 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
717 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
718 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
719 }
720
721 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
722 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
723 TrafficSched[0].TechProfileId = sq.tpID
724
725 // Remove traffic queues. Ignore any errors, just log them.
726 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
727 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
728 "direction": sq.direction,
729 "intf-id": sq.intfID,
730 "onu-id": sq.onuID,
731 "uni-id": sq.uniID,
732 "uni-port": sq.uniPort,
733 "tp-id": sq.tpID,
734 "device-id": f.deviceHandler.device.Id,
735 "err": err})
736 } else {
737 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
738 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
739 UniId: sq.uniID, PortNo: sq.uniPort,
740 TrafficQueues: TrafficQueues,
741 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
742 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
743 "direction": sq.direction,
744 "intf-id": sq.intfID,
745 "onu-id": sq.onuID,
746 "uni-id": sq.uniID,
747 "uni-port": sq.uniPort,
748 "tp-id": sq.tpID,
749 "device-id": f.deviceHandler.device.Id,
750 "err": err})
751
752 } else {
753 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
754 "direction": sq.direction,
755 "intf-id": sq.intfID,
756 "onu-id": sq.onuID,
757 "uni-id": sq.uniID,
758 "uni-port": sq.uniPort,
759 "tp-id": sq.tpID})
760 }
761 }
762
763 // Remove traffic schedulers. Ignore any errors, just log them.
764 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
765 IntfId: sq.intfID, OnuId: sq.onuID,
766 UniId: sq.uniID, PortNo: sq.uniPort,
767 TrafficScheds: TrafficSched}); err != nil {
768 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
769 "direction": sq.direction,
770 "intf-id": sq.intfID,
771 "onu-id": sq.onuID,
772 "uni-id": sq.uniID,
773 "uni-port": sq.uniPort,
774 "tp-id": sq.tpID,
775 "device-id": f.deviceHandler.device.Id,
776 "err": err})
777 } else {
778 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
779 "direction": sq.direction,
780 "intf-id": sq.intfID,
781 "onu-id": sq.onuID,
782 "uni-id": sq.uniID,
783 "uni-port": sq.uniPort,
784 "tp-id": sq.tpID})
785 }
786}
787
Gamze Abakafee36392019-10-03 11:17:24 +0000788// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700789func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) (uint32, []uint32, interface{}) {
Gamze Abakafee36392019-10-03 11:17:24 +0000790 var allocIDs []uint32
791 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530792 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530793 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000794 var err error
npujarec5762e2020-01-01 14:08:48 +0530795 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
796 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000797 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530798
Neha Sharma96b7bf22020-06-15 10:37:32 +0000799 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530800 "intf-id": intfID,
801 "onu-id": onuID,
802 "uni-id": uniID,
803 "device-id": f.deviceHandler.device.Id,
804 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530805
Manikkaraj kb1d51442019-07-23 10:41:02 -0400806 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700807 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000808 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000809 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530810 log.Fields{
811 "path": tpPath,
812 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700813 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000814 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530815 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000816 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530817 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700818 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530819 "tp-id": TpID,
820 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000821 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530822 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400823 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700824 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400825 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530826 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000827 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530828 log.Fields{
829 "uni": uni,
830 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530831 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530832 }
Gamze Abakafee36392019-10-03 11:17:24 +0000833
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700834 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700835 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700836 if UsMeterID != 0 {
837 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
838 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
839 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000840 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700841 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700842 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700843 "onu-id": onuID,
844 "uni-id": uniID,
845 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700846 "meter-id": UsMeterID,
847 "device-id": f.deviceHandler.device.Id})
848 return 0, nil, nil
849 }
850 }
851 if DsMeterID != 0 {
852 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
853 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
854 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000855 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700856 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700857 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700858 "onu-id": onuID,
859 "uni-id": uniID,
860 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700861 "meter-id": DsMeterID,
862 "device-id": f.deviceHandler.device.Id})
863 return 0, nil, nil
864 }
865 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700866 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700867 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700868 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700869 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700870 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000871
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700872 if tpInstanceExists {
873 return allocID, gemPortIDs, techProfileInstance
874 }
875
876 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700877 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700878 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000879 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700880 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700881 "intf-id": intfID,
882 "onu-id": onuID,
883 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700884 "alloc-ids": allocIDs,
885 "gemports": allgemPortIDs,
886 "device-id": f.deviceHandler.device.Id})
887 // Send Tconts and GEM ports to KV store
888 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530889 return allocID, gemPortIDs, techProfileInstance
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700890 case *openoltpb2.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700891 // CreateSchedulerQueues for EPON needs to be implemented here
892 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700893 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700894 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700895 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700896 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700897 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700898
899 if tpInstanceExists {
900 return allocID, gemPortIDs, techProfileInstance
901 }
902
903 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700904 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700905 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000906 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700907 log.Fields{
908 "alloc-ids": allocIDs,
909 "gemports": allgemPortIDs,
910 "device-id": f.deviceHandler.device.Id})
911 // Send Tconts and GEM ports to KV store
912 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
913 return allocID, gemPortIDs, techProfileInstance
914 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000915 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700916 log.Fields{
917 "tpInst": tpInst})
918 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530919 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530920}
921
npujarec5762e2020-01-01 14:08:48 +0530922func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530923
Neha Sharma96b7bf22020-06-15 10:37:32 +0000924 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530925 log.Fields{
926 "intf-id": intfID,
927 "onu-id": onuID,
928 "uni-id": uniID,
929 "alloc-id": allocID,
930 "gemport-ids": gemPortIDs,
931 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530932 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530933 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000934 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 +0530935 }
npujarec5762e2020-01-01 14:08:48 +0530936 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000937 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 +0530938 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700939
Neha Sharma96b7bf22020-06-15 10:37:32 +0000940 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 -0400941 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530942 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400943 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530944}
945
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700946func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530947 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000948 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700949 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
950 var err error
951 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
952 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
953 if err != nil || f.techprofile == nil {
954 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
955 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
956 }
957 logger.Debugw(ctx, "init-tech-profile-done",
958 log.Fields{
959 "intf-id": intfID,
960 "device-id": f.deviceHandler.device.Id})
961 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700962 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530963 }
964 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700965 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
966 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 +0530967}
968
Gamze Abaka7650be62021-02-26 10:50:36 +0000969func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
970 flowContext.classifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000971 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530972 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000973 "uplinkClassifier": flowContext.classifier,
974 "uplinkAction": flowContext.action})
975 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530976 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530977}
978
Gamze Abaka7650be62021-02-26 10:50:36 +0000979func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
980 downlinkClassifier := flowContext.classifier
981 downlinkAction := flowContext.action
982
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700983 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000984 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530985 log.Fields{
986 "downlinkClassifier": downlinkClassifier,
987 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400988 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
989 if vlan, exists := downlinkClassifier[VlanVid]; exists {
990 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700991 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Gamze Abaka7650be62021-02-26 10:50:36 +0000992 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000993 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530994 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000995 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +0530996 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +0000997 "onu-id": flowContext.onuID,
998 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800999 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -04001000 }
1001 }
1002 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301003 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001004
Manikkaraj k884c1242019-04-11 16:26:42 +05301005 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001006 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -04001007 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1008 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +05301009 if ok {
1010 downlinkAction[VlanVid] = dlClVid & 0xfff
1011 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05301012 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301013 "reason": "failed-to-convert-vlanid-classifier",
1014 "vlan-id": VlanVid,
1015 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +05301016 }
1017
Gamze Abaka7650be62021-02-26 10:50:36 +00001018 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301019}
1020
Gamze Abaka7650be62021-02-26 10:50:36 +00001021func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001022
Gamze Abaka7650be62021-02-26 10:50:36 +00001023 intfID := flowContext.intfID
1024 onuID := flowContext.onuID
1025 uniID := flowContext.uniID
1026 classifier := flowContext.classifier
1027 action := flowContext.action
1028 allocID := flowContext.allocID
1029 gemPortID := flowContext.gemPortID
1030 tpID := flowContext.tpID
1031 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001032 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301033 log.Fields{
1034 "intf-id": intfID,
1035 "onu-id": onuID,
1036 "uni-id": uniID,
1037 "device-id": f.deviceHandler.device.Id,
1038 "classifier": classifier,
1039 "action": action,
1040 "direction": direction,
1041 "alloc-id": allocID,
1042 "gemport-id": gemPortID,
1043 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001044
1045 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001046 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301047 log.Fields{
1048 "device-id": f.deviceHandler.device.Id,
1049 "intf-id": intfID,
1050 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001051 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301052 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001053 classifierProto, err := makeOpenOltClassifierField(classifier)
1054 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301055 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301056 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001057 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301058 log.Fields{
1059 "classifier": *classifierProto,
1060 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001061 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001062 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301063 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301064 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001065 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301066 log.Fields{
1067 "action": *actionProto,
1068 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001069 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301070 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301071 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001072 log.Fields{
1073 "classifier": classifier,
1074 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301075 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001076 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301077 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001078
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001079 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001080 OnuId: int32(onuID),
1081 UniId: int32(uniID),
1082 FlowId: logicalFlow.Id,
1083 FlowType: direction,
1084 AllocId: int32(allocID),
1085 NetworkIntfId: int32(networkIntfID),
1086 GemportId: int32(gemPortID),
1087 Classifier: classifierProto,
1088 Action: actionProto,
1089 Priority: int32(logicalFlow.Priority),
1090 Cookie: logicalFlow.Cookie,
1091 PortNo: flowContext.portNo,
1092 TechProfileId: tpID,
1093 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1094 PbitToGemport: flowContext.pbitToGem,
1095 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001096 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001097 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001098 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301099 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001100 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301101 log.Fields{"direction": direction,
1102 "device-id": f.deviceHandler.device.Id,
1103 "flow": flow,
1104 "intf-id": intfID,
1105 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001106
David K. Bainbridge794735f2020-02-11 21:01:37 -08001107 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301108}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001109
Gamze Abaka7650be62021-02-26 10:50:36 +00001110func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1111
1112 intfID := flowContext.intfID
1113 onuID := flowContext.onuID
1114 uniID := flowContext.uniID
1115 logicalFlow := flowContext.logicalFlow
1116 classifier := flowContext.classifier
1117 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301118
Neha Sharma96b7bf22020-06-15 10:37:32 +00001119 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301120 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301121 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001122 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301123 "action": action,
1124 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001125 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301126 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301127
1128 // Clear the action map
1129 for k := range action {
1130 delete(action, k)
1131 }
1132
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001133 action[TrapToHost] = true
1134 classifier[UDPSrc] = uint32(68)
1135 classifier[UDPDst] = uint32(67)
1136 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301137
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001138 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001139 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301140 log.Fields{
1141 "device-id": f.deviceHandler.device.Id,
1142 "intf-id": intfID,
1143 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001144 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301145 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301146
Neha Sharma96b7bf22020-06-15 10:37:32 +00001147 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301148 log.Fields{
1149 "ul_classifier": classifier,
1150 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001151 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301152 "intf-id": intfID,
1153 "onu-id": onuID,
1154 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301155
David K. Bainbridge794735f2020-02-11 21:01:37 -08001156 classifierProto, err := makeOpenOltClassifierField(classifier)
1157 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301158 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301159 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001160 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001161 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001162 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301163 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301164 }
1165
David K. Bainbridge794735f2020-02-11 21:01:37 -08001166 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001167 OnuId: int32(onuID),
1168 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001169 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001170 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001171 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001172 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001173 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301174 Classifier: classifierProto,
1175 Action: actionProto,
1176 Priority: int32(logicalFlow.Priority),
1177 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001178 PortNo: flowContext.portNo,
1179 TechProfileId: flowContext.tpID,
1180 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1181 PbitToGemport: flowContext.pbitToGem,
1182 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001183 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001184 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001185 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001186 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001187 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301188 log.Fields{
1189 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001190 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301191 "intf-id": intfID,
1192 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301193
David K. Bainbridge794735f2020-02-11 21:01:37 -08001194 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301195}
1196
Esin Karamanae41e2b2019-12-17 18:13:13 +00001197//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001198func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1199 delete(flowContext.classifier, VlanVid)
1200 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001201}
1202
1203//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001204func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1205
1206 intfID := flowContext.intfID
1207 onuID := flowContext.onuID
1208 uniID := flowContext.uniID
1209 logicalFlow := flowContext.logicalFlow
1210 classifier := flowContext.classifier
1211 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001212
Neha Sharma96b7bf22020-06-15 10:37:32 +00001213 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001214 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301215 return olterrors.NewErrNotFound("nni-interface-id",
1216 log.Fields{
1217 "classifier": classifier,
1218 "action": action,
1219 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001220 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001221 }
1222
1223 // Clear the action map
1224 for k := range action {
1225 delete(action, k)
1226 }
1227
1228 action[TrapToHost] = true
1229 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001230
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001231 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001232 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001233 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001234 }
1235
Neha Sharma96b7bf22020-06-15 10:37:32 +00001236 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301237 log.Fields{
1238 "ul_classifier": classifier,
1239 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001240 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301241 "device-id": f.deviceHandler.device.Id,
1242 "intf-id": intfID,
1243 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001244
David K. Bainbridge794735f2020-02-11 21:01:37 -08001245 classifierProto, err := makeOpenOltClassifierField(classifier)
1246 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301247 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001248 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001249 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301250 log.Fields{
1251 "classifier": *classifierProto,
1252 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001253 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001254 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301255 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001256 }
1257
David K. Bainbridge794735f2020-02-11 21:01:37 -08001258 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001259 OnuId: int32(onuID),
1260 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001261 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001262 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001263 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001264 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001265 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001266 Classifier: classifierProto,
1267 Action: actionProto,
1268 Priority: int32(logicalFlow.Priority),
1269 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001270 PortNo: flowContext.portNo,
1271 TechProfileId: flowContext.tpID,
1272 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1273 PbitToGemport: flowContext.pbitToGem,
1274 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001275 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001276
David K. Bainbridge794735f2020-02-11 21:01:37 -08001277 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001278 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 -08001279 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001280
David K. Bainbridge794735f2020-02-11 21:01:37 -08001281 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001282}
1283
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001284// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001285func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1286 intfID := flowContext.intfID
1287 onuID := flowContext.onuID
1288 uniID := flowContext.uniID
1289 portNo := flowContext.portNo
1290 allocID := flowContext.allocID
1291 gemPortID := flowContext.gemPortID
1292 logicalFlow := flowContext.logicalFlow
1293 classifier := flowContext.classifier
1294 action := flowContext.action
1295
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001296 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301297 log.Fields{
1298 "intf-id": intfID,
1299 "onu-id": onuID,
1300 "port-no": portNo,
1301 "alloc-id": allocID,
1302 "gemport-id": gemPortID,
1303 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001304 "flow": logicalFlow,
1305 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301306
1307 uplinkClassifier := make(map[string]interface{})
1308 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301309
manikkaraj kbf256be2019-03-25 00:13:48 +05301310 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001311 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001312 uplinkClassifier[PacketTagType] = SingleTag
1313 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001314 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301315 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001316 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001317 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001318 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301319 "device-id": f.deviceHandler.device.Id,
1320 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001321 "intf-id": intfID,
1322 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001323 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301324 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001325 //Add Uplink EthType Flow
1326 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301327 log.Fields{
1328 "ul_classifier": uplinkClassifier,
1329 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001330 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301331 "device-id": f.deviceHandler.device.Id,
1332 "intf-id": intfID,
1333 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301334
David K. Bainbridge794735f2020-02-11 21:01:37 -08001335 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1336 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301337 return olterrors.NewErrInvalidValue(log.Fields{
1338 "classifier": uplinkClassifier,
1339 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301340 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001341 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301342 log.Fields{
1343 "classifier": *classifierProto,
1344 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001345 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001346 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301347 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301348 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001349 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301350 log.Fields{
1351 "action": *actionProto,
1352 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001353 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301354 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301355 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001356 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301357 "action": action,
1358 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001359 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301360 }
1361
David K. Bainbridge794735f2020-02-11 21:01:37 -08001362 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001363 OnuId: int32(onuID),
1364 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001365 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001366 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001367 AllocId: int32(allocID),
1368 NetworkIntfId: int32(networkIntfID),
1369 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301370 Classifier: classifierProto,
1371 Action: actionProto,
1372 Priority: int32(logicalFlow.Priority),
1373 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001374 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001375 TechProfileId: flowContext.tpID,
1376 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1377 PbitToGemport: flowContext.pbitToGem,
1378 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001379 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001380 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001381 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001382 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001383 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301384 log.Fields{
1385 "device-id": f.deviceHandler.device.Id,
1386 "onu-id": onuID,
1387 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001388 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301389 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001390
David K. Bainbridge794735f2020-02-11 21:01:37 -08001391 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301392}
1393
David K. Bainbridge794735f2020-02-11 21:01:37 -08001394func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001395 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001396
1397 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1398 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1399 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001400 if vlanID != ReservedVlan {
1401 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001402 classifier.OVid = vid
1403 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301404 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001405 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1406 vid := uint32(metadata)
1407 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001408 classifier.IVid = vid
1409 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301410 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301411 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001412 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301413 classifier.OPbits = vlanPcp
1414 } else {
1415 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301416 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001417 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1418 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1419 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1420 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001421 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001422 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1423 classifier.PktTagType = pktTagType
1424
1425 switch pktTagType {
1426 case SingleTag:
1427 case DoubleTag:
1428 case Untagged:
1429 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001430 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301431 }
1432 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001433 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301434}
1435
Gamze Abaka724d0852020-03-18 12:10:24 +00001436func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001437 var actionCmd openoltpb2.ActionCmd
1438 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301439 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001440 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301441 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001442 if _, ok := actionInfo[VlanPcp]; ok {
1443 action.Cmd.RemarkInnerPbits = true
1444 action.IPbits = actionInfo[VlanPcp].(uint32)
1445 if _, ok := actionInfo[VlanVid]; ok {
1446 action.Cmd.TranslateInnerTag = true
1447 action.IVid = actionInfo[VlanVid].(uint32)
1448 }
1449 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001450 } else if _, ok := actionInfo[PushVlan]; ok {
1451 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301452 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001453 if _, ok := actionInfo[VlanPcp]; ok {
1454 action.OPbits = actionInfo[VlanPcp].(uint32)
1455 action.Cmd.RemarkOuterPbits = true
1456 if _, ok := classifierInfo[VlanVid]; ok {
1457 action.IVid = classifierInfo[VlanVid].(uint32)
1458 action.Cmd.TranslateInnerTag = true
1459 }
1460 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001461 } else if _, ok := actionInfo[TrapToHost]; ok {
1462 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301463 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001464 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301465 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001466 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301467}
1468
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001469// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001470func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001471 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301472}
1473
Gamze Abakafee36392019-10-03 11:17:24 +00001474// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001475// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1476// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1477// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1478// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1479// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1480// because it was observed that if the ONU device was deleted too soon after the flows were
1481// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1482// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1483// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001484func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301485 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001486 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1487
Gamze Abakafee36392019-10-03 11:17:24 +00001488 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001489
1490 // Force cleanup scheduler/queues -- start
1491 uniPortNum := MkUniPortNum(ctx, intfID, onuID, uniID)
1492 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1493 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
1494 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1495 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1496 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1497 log.Fields{
1498 "tp-id": tpID,
1499 "path": tpPath})
1500 }
1501 switch tpInstance := tpInst.(type) {
1502 case *tp_pb.TechProfileInstance:
1503 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1504 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1505 }
1506 // Force cleanup scheduler/queues -- end
1507
1508 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301509 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001510 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301511 // return err
1512 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001513 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001514 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 +00001515 }
1516 return nil
1517}
1518
1519// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301520func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001521 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001522 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001523 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001524 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301525 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1526 log.Fields{
1527 "tp-id": tpID,
1528 "uni-port-name": uniPortName,
1529 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001530 }
1531 return nil
1532}
1533
David K. Bainbridge794735f2020-02-11 21:01:37 -08001534func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001535
1536 var intfID uint32
1537 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1538 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1539 */
1540 if deviceFlow.AccessIntfId != -1 {
1541 intfID = uint32(deviceFlow.AccessIntfId)
1542 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001543 // We need to log the valid interface ID.
1544 // 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 +00001545 intfID = uint32(deviceFlow.NetworkIntfId)
1546 }
1547
Neha Sharma96b7bf22020-06-15 10:37:32 +00001548 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301549 "flow": *deviceFlow,
1550 "device-id": f.deviceHandler.device.Id,
1551 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001552 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001553
1554 st, _ := status.FromError(err)
1555 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001556 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001557 "err": err,
1558 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301559 "device-id": f.deviceHandler.device.Id,
1560 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001561 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301562 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001563
1564 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001565 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301566 log.Fields{"err": err,
1567 "device-flow": deviceFlow,
1568 "device-id": f.deviceHandler.device.Id,
1569 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001570 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001571 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001572 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301573 log.Fields{
1574 "flow": *deviceFlow,
1575 "device-id": f.deviceHandler.device.Id,
1576 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001577
1578 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1579 if deviceFlow.AccessIntfId != -1 {
1580 // No need to register the flow if it is a trap on nni flow.
1581 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1582 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1583 return err
1584 }
1585 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001586 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001587}
1588
Neha Sharma96b7bf22020-06-15 10:37:32 +00001589func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1590 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301591 log.Fields{
1592 "flow": *deviceFlow,
1593 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001594 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001595 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001596 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001597 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301598 log.Fields{
1599 "err": err,
1600 "deviceFlow": deviceFlow,
1601 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001602 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001603 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001604 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001605 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001606
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001607 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001608 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001609 "of-flow-id": ofFlowID,
1610 "flow": *deviceFlow,
1611 "device-id": f.deviceHandler.device.Id,
1612 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001613 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301614}
1615
David K. Bainbridge794735f2020-02-11 21:01:37 -08001616func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001617
1618 classifierInfo := make(map[string]interface{})
1619 actionInfo := make(map[string]interface{})
1620
1621 classifierInfo[EthType] = uint32(LldpEthType)
1622 classifierInfo[PacketTagType] = Untagged
1623 actionInfo[TrapToHost] = true
1624
1625 // LLDP flow is installed to trap LLDP packets on the NNI port.
1626 // We manage flow_id resource pool on per PON port basis.
1627 // Since this situation is tricky, as a hack, we pass the NNI port
1628 // index (network_intf_id) as PON port Index for the flow_id resource
1629 // pool. Also, there is no ONU Id available for trapping LLDP packets
1630 // on NNI port, use onu_id as -1 (invalid)
1631 // ****************** CAVEAT *******************
1632 // This logic works if the NNI Port Id falls within the same valid
1633 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1634 // we need to have a re-look at this.
1635 // *********************************************
1636
1637 var onuID = -1
1638 var uniID = -1
1639 var gemPortID = -1
1640
Neha Sharma96b7bf22020-06-15 10:37:32 +00001641 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001642 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301643 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001644 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001645 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001646 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001647 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001648 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001649
David K. Bainbridge794735f2020-02-11 21:01:37 -08001650 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1651 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301652 return olterrors.NewErrInvalidValue(
1653 log.Fields{
1654 "classifier": classifierInfo,
1655 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001656 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001657 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301658 log.Fields{
1659 "classifier": *classifierProto,
1660 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001661 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001662 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301663 return olterrors.NewErrInvalidValue(
1664 log.Fields{
1665 "action": actionInfo,
1666 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001667 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001668 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301669 log.Fields{
1670 "action": *actionProto,
1671 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001672
1673 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1674 OnuId: int32(onuID), // OnuId not required
1675 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001676 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001677 FlowType: Downstream,
1678 NetworkIntfId: int32(networkInterfaceID),
1679 GemportId: int32(gemPortID),
1680 Classifier: classifierProto,
1681 Action: actionProto,
1682 Priority: int32(flow.Priority),
1683 Cookie: flow.Cookie,
1684 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001685 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001686 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301687 log.Fields{
1688 "flow": downstreamflow,
1689 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001690 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001691 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301692 log.Fields{
1693 "device-id": f.deviceHandler.device.Id,
1694 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001695 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001696
David K. Bainbridge794735f2020-02-11 21:01:37 -08001697 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301698}
1699
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001700func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1701 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001702}
1703
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001704//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001705func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001706 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1707 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1708 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001709 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301710 log.Fields{
1711 "intf-id": intfID,
1712 "onu-id": onuID,
1713 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001714 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001715 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301716 return nil, olterrors.NewErrNotFound("onu-child-device",
1717 log.Fields{
1718 "onu-id": onuID,
1719 "intf-id": intfID,
1720 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001721 }
1722 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1723 //better to ad the device to cache here.
1724 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1725 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001726 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301727 log.Fields{
1728 "intf-id": intfID,
1729 "onu-id": onuID,
1730 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001731 }
1732
1733 return onuDev.(*OnuDevice), nil
1734}
1735
1736//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001737func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1738 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301739 log.Fields{
1740 "pon-port": intfID,
1741 "onu-id": onuID,
1742 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001743 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001744 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001745 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301746 return nil, olterrors.NewErrNotFound("onu",
1747 log.Fields{
1748 "interface-id": parentPortNo,
1749 "onu-id": onuID,
1750 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001751 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301752 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001753 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301754 log.Fields{
1755 "device-id": f.deviceHandler.device.Id,
1756 "child_device_id": onuDevice.Id,
1757 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301758 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301759}
1760
Neha Sharma96b7bf22020-06-15 10:37:32 +00001761func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1762 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301763 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001764 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301765 log.Fields{
1766 "intf-id": intfID,
1767 "onu-id": onuID,
1768 "uni-id": uniID,
1769 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001770 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301771 }
1772
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001773 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpInstancePath: tpPath, GemPortId: gemPortID}
1774 logger.Infow(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301775 log.Fields{
1776 "msg": *delGemPortMsg,
1777 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001778 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301779 delGemPortMsg,
1780 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001781 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001782 onuDev.deviceType,
1783 onuDev.deviceID,
1784 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301785 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1786 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001787 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301788 "to-adapter": onuDev.deviceType,
1789 "onu-id": onuDev.deviceID,
1790 "proxyDeviceID": onuDev.proxyDeviceID,
1791 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301792 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001793 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301794 log.Fields{
1795 "msg": delGemPortMsg,
1796 "from-adapter": f.deviceHandler.device.Type,
1797 "to-adapter": onuDev.deviceType,
1798 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301799 return nil
1800}
1801
Neha Sharma96b7bf22020-06-15 10:37:32 +00001802func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1803 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301804 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001805 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301806 log.Fields{
1807 "intf-id": intfID,
1808 "onu-id": onuID,
1809 "uni-id": uniID,
1810 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001811 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301812 }
1813
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001814 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpInstancePath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001815 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301816 log.Fields{
1817 "msg": *delTcontMsg,
1818 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001819 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301820 delTcontMsg,
1821 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001822 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001823 onuDev.deviceType,
1824 onuDev.deviceID,
1825 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301826 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1827 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001828 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301829 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1830 "proxyDeviceID": onuDev.proxyDeviceID,
1831 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301832 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001833 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301834 log.Fields{
1835 "msg": delTcontMsg,
1836 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301837 return nil
1838}
1839
Girish Gowdrac3037402020-01-22 20:29:53 +05301840// Once the gemport is released for a given onu, it also has to be cleared from local cache
1841// which was used for deriving the gemport->logicalPortNo during packet-in.
1842// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1843// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001844func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001845 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301846 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001847 "gem-port-id": gemPortID,
1848 "intf-id": intfID,
1849 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001850 "device-id": f.deviceHandler.device.Id})
1851 f.onuGemInfoLock.RLock()
1852 onugem, ok := f.onuGemInfoMap[onuID]
1853 f.onuGemInfoLock.RUnlock()
1854 if !ok {
1855 logger.Warnw(ctx, "onu gem info already cleared from cache", log.Fields{
1856 "gem-port-id": gemPortID,
1857 "intf-id": intfID,
1858 "onu-id": onuID,
1859 "device-id": f.deviceHandler.device.Id})
1860 return
1861 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001862deleteLoop:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001863 for j, gem := range onugem.GemPorts {
1864 // If the gemport is found, delete it from local cache.
1865 if gem == gemPortID {
1866 onugem.GemPorts = append(onugem.GemPorts[:j], onugem.GemPorts[j+1:]...)
1867 f.onuGemInfoLock.Lock()
1868 f.onuGemInfoMap[onuID] = onugem
1869 f.onuGemInfoLock.Unlock()
1870 logger.Infow(ctx, "removed-gemport-from-local-cache",
1871 log.Fields{
1872 "intf-id": intfID,
1873 "onu-id": onuID,
1874 "deletedgemport-id": gemPortID,
1875 "gemports": onugem.GemPorts,
1876 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001877 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301878 }
1879 }
1880}
1881
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301882//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001883// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001884func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Girish Gowdra82c80982021-03-26 16:22:02 -07001885 gemPortID int32, flowID uint64, portNum uint32, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001886
Girish Gowdraa482f272021-03-24 23:04:19 -07001887 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1888 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001889 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1890 log.Fields{
1891 "tpPath": tpPath,
1892 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001893
1894 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1895
1896 if used {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001897 f.gemToFlowIDsKey.RLock()
1898 flowIDs := f.gemToFlowIDs[uint32(gemPortID)]
1899 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001900
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001901 for i, flowIDinMap := range flowIDs {
1902 if flowIDinMap == flowID {
1903 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001904 f.gemToFlowIDsKey.Lock()
1905 f.gemToFlowIDs[uint32(gemPortID)] = flowIDs
1906 f.gemToFlowIDsKey.Unlock()
1907 // everytime gemToFlowIDs cache is updated the same should be updated
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001908 // in kv store by calling UpdateFlowIDsForGem
Girish Gowdraa482f272021-03-24 23:04:19 -07001909 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001910 return err
1911 }
1912 break
1913 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001914 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001915 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1916 log.Fields{
1917 "gemport-id": gemPortID,
1918 "usedByFlows": flowIDs,
1919 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001920
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001921 return nil
1922 }
1923 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
Girish Gowdraa482f272021-03-24 23:04:19 -07001924 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001925 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), uint32(gemPortID)) // ignore error and proceed.
1926 //everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001927 // by calling DeleteFlowIDsForGem
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001928 f.gemToFlowIDsKey.Lock()
1929 delete(f.gemToFlowIDs, uint32(gemPortID))
1930 f.gemToFlowIDsKey.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001931
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001932 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1933
1934 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001935
Mahir Gunyel199570a2021-07-04 15:39:36 -07001936 //First remove TCONT from child if needed. Then remove the GEM.
1937 //It is expected from child to clean ani side conf if all GEMs of TP are deleted.
1938 //Before this, ensure that the related TCONT deletions are informed to child.
1939 //Refer to VOL-4215.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001940 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1941 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1942 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1943 log.Fields{
1944 "tp-id": tpID,
1945 "path": tpPath}, err)
1946 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001947 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001948 case *tp_pb.TechProfileInstance:
Gamze Abakacb0e6772021-06-10 08:32:12 +00001949 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst, uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001950 if !ok {
Girish Gowdraa482f272021-03-24 23:04:19 -07001951 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001952 logger.Warn(ctx, err)
1953 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001954 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001955 logger.Warn(ctx, err)
1956 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001957 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001958 logger.Warn(ctx, err)
1959 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001960 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001961 logger.Warn(ctx, err)
1962 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001963 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001964 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07001965 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001966 logger.Warn(ctx, err)
1967 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001968 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001969 logger.Warn(ctx, err)
1970 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001971 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001972 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001973 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001974 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301975 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07001976 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05301977 "onu-id": onuID,
1978 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001979 "device-id": f.deviceHandler.device.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001980 "alloc-id": techprofileInst.AllocId})
Gamze Abakafee36392019-10-03 11:17:24 +00001981 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001982 default:
1983 logger.Errorw(ctx, "error-unknown-tech",
1984 log.Fields{
1985 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001986 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001987
Mahir Gunyel199570a2021-07-04 15:39:36 -07001988 // Delete the gem port on the ONU. Send Gem Removal After TCONT removal.
1989 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1990 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1991 log.Fields{
1992 "err": err,
1993 "intfID": intfID,
1994 "onu-id": onuID,
1995 "uni-id": uniID,
1996 "device-id": f.deviceHandler.device.Id,
1997 "gemport-id": gemPortID})
1998 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301999 return nil
2000}
2001
David K. Bainbridge794735f2020-02-11 21:01:37 -08002002// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002003func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002004 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302005 log.Fields{
2006 "flowDirection": flowDirection,
2007 "flow": *flow,
2008 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002009
2010 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002011 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002012 }
2013
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302014 classifierInfo := make(map[string]interface{})
2015
Neha Sharma96b7bf22020-06-15 10:37:32 +00002016 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302017 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002018 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002019 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302020 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302021
David K. Bainbridge794735f2020-02-11 21:01:37 -08002022 onuID := int32(onu)
2023 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002024 tpID, err := getTpIDFromFlow(ctx, flow)
2025 if err != nil {
2026 return olterrors.NewErrNotFound("tp-id",
2027 log.Fields{
2028 "flow": flow,
2029 "intf-id": Intf,
2030 "onu-id": onuID,
2031 "uni-id": uniID,
2032 "device-id": f.deviceHandler.device.Id}, err)
2033 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302034
2035 for _, field := range flows.GetOfbFields(flow) {
2036 if field.Type == flows.IP_PROTO {
2037 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002038 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302039 }
2040 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002041 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302042 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002043 "flow-id": flow.Id,
2044 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302045 "onu-id": onuID,
2046 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302047
2048 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2049 onuID = -1
2050 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002051 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2052 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002053 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002054 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002055 log.Fields{
2056 "port-number": inPort,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002057 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002058 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002059 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302060 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002061
2062 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2063 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002064 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2065 return err
2066 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002067
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002068 f.flowIDToGemsLock.Lock()
2069 gems, ok := f.flowIDToGems[flow.Id]
2070 if !ok {
2071 logger.Errorw(ctx, "flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id})
2072 f.flowIDToGemsLock.Unlock()
2073 return olterrors.NewErrNotFound("flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id}, nil)
2074 }
2075 copyOfGems := make([]uint32, len(gems))
2076 _ = copy(copyOfGems, gems)
2077 // Delete the flow-id to gemport list entry from the map now the flow is deleted.
2078 delete(f.flowIDToGems, flow.Id)
2079 f.flowIDToGemsLock.Unlock()
2080
2081 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": copyOfGems})
2082 for _, gem := range copyOfGems {
2083 if err = f.clearResources(ctx, Intf, onuID, uniID, int32(gem), flow.Id, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002084 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002085 "flow-id": flow.Id,
2086 "device-id": f.deviceHandler.device.Id,
2087 "onu-id": onuID,
2088 "intf": Intf,
2089 "gem": gem,
2090 "err": err,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002091 })
2092 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302093 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302094 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002095
Girish Gowdra82c80982021-03-26 16:22:02 -07002096 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2097 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2098 return err
2099 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002100 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002101}
2102
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002103//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002104func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002105
Matteo Scandolof16389e2021-05-18 00:47:08 +00002106 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302107 var direction string
2108 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002109
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302110 for _, action := range flows.GetActions(flow) {
2111 if action.Type == flows.OUTPUT {
2112 if out := action.GetOutput(); out != nil {
2113 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002114 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302115 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002116 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002117 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002118 }
2119 }
2120 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002121
2122 if flows.HasGroup(flow) {
2123 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002124 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002125 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302126 direction = Upstream
2127 } else {
2128 direction = Downstream
2129 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302130
Girish Gowdracefae192020-03-19 18:14:10 -07002131 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002132 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002133
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002134 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002135}
2136
Esin Karamanae41e2b2019-12-17 18:13:13 +00002137//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2138func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2139 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2140 if ethType, ok := classifierInfo[EthType]; ok {
2141 if ethType.(uint32) == IPv4EthType {
2142 if ipProto, ok := classifierInfo[IPProto]; ok {
2143 if ipProto.(uint32) == IgmpProto {
2144 return true
2145 }
2146 }
2147 }
2148 }
2149 }
2150 return false
2151}
2152
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002153// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2154func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2155 // Step1 : Fill flowControlBlock
2156 // Step2 : Push the flowControlBlock to ONU channel
2157 // Step3 : Wait on response channel for response
2158 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002159 startTime := time.Now()
2160 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002161 errChan := make(chan error)
2162 flowCb := flowControlBlock{
2163 ctx: ctx,
2164 addFlow: addFlow,
2165 flow: flow,
2166 flowMetadata: flowMetadata,
2167 errChan: &errChan,
2168 }
2169 inPort, outPort := getPorts(flow)
2170 var onuID uint32
2171 if inPort != InvalidPort && outPort != InvalidPort {
2172 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2173 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002174 if f.flowHandlerRoutineActive[onuID] {
2175 // inPort or outPort is InvalidPort for trap-from-nni flows.
2176 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2177 // Send the flowCb on the ONU flow channel
2178 f.incomingFlows[onuID] <- flowCb
2179 // Wait on the channel for flow handlers return value
2180 err := <-errChan
2181 logger.Infow(ctx, "process-flow--received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
2182 return err
2183 }
2184 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2185 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002186}
2187
2188// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2189// 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 -07002190func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002191 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002192 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002193 // block on the channel to receive an incoming flow
2194 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002195 case flowCb := <-subscriberFlowChannel:
2196 if flowCb.addFlow {
2197 logger.Info(flowCb.ctx, "adding-flow-start")
2198 startTime := time.Now()
2199 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2200 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2201 // Pass the return value over the return channel
2202 *flowCb.errChan <- err
2203 } else {
2204 logger.Info(flowCb.ctx, "removing-flow-start")
2205 startTime := time.Now()
2206 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2207 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2208 // Pass the return value over the return channel
2209 *flowCb.errChan <- err
2210 }
2211 case <-stopHandler:
2212 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2213 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002214 }
2215 }
2216}
2217
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002218// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
2219func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context) {
2220 for i, v := range f.stopFlowHandlerRoutine {
2221 if f.flowHandlerRoutineActive[i] {
2222 v <- true
2223 }
2224 }
2225 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2226}
2227
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002228// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302229// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002230func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002231 classifierInfo := make(map[string]interface{})
2232 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002233 var UsMeterID uint32
2234 var DsMeterID uint32
2235
Neha Sharma96b7bf22020-06-15 10:37:32 +00002236 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302237 log.Fields{
2238 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002239 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002240 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002241
Neha Sharma96b7bf22020-06-15 10:37:32 +00002242 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002243 if err != nil {
2244 // Error logging is already done in the called function
2245 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002246 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302247 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002248
Esin Karamanccb714b2019-11-29 15:02:06 +00002249 if flows.HasGroup(flow) {
2250 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002251 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002252 }
2253
manikkaraj k17652a72019-05-06 09:06:36 -04002254 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002255 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002256 if err != nil {
2257 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002258 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002259 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002260
Neha Sharma96b7bf22020-06-15 10:37:32 +00002261 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302262 log.Fields{
2263 "classifierinfo_inport": classifierInfo[InPort],
2264 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002265 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002266
Humera Kouser94d7a842019-08-25 19:04:32 -04002267 if ethType, ok := classifierInfo[EthType]; ok {
2268 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002269 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002270 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002271 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002272 if ethType.(uint32) == PPPoEDEthType {
2273 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2274 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2275 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2276 }
2277 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002278 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002279 if ipProto, ok := classifierInfo[IPProto]; ok {
2280 if ipProto.(uint32) == IPProtoDhcp {
2281 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302282 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002283 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002284 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002285 }
2286 }
2287 }
2288 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002289 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002290 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002291 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002292 }
A R Karthick1f85b802019-10-11 05:06:05 +00002293
npujarec5762e2020-01-01 14:08:48 +05302294 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002295 // also update flowmgr cache
2296 f.onuGemInfoLock.Lock()
2297 onugem, ok := f.onuGemInfoMap[onuID]
2298 if ok {
2299 found := false
2300 for _, uni := range onugem.UniPorts {
2301 if uni == portNo {
2302 found = true
2303 break
2304 }
2305 }
2306 if !found {
2307 onugem.UniPorts = append(onugem.UniPorts, portNo)
2308 f.onuGemInfoMap[onuID] = onugem
2309 logger.Infow(ctx, "added uni port to onugem cache", log.Fields{"uni": portNo})
2310 }
2311 }
2312 f.onuGemInfoLock.Unlock()
A R Karthick1f85b802019-10-11 05:06:05 +00002313
Neha Sharma96b7bf22020-06-15 10:37:32 +00002314 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002315 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302316 return olterrors.NewErrNotFound("tpid-for-flow",
2317 log.Fields{
2318 "flow": flow,
2319 "intf-id": IntfID,
2320 "onu-id": onuID,
2321 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002322 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002323 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302324 log.Fields{
2325 "tp-id": TpID,
2326 "intf-id": intfID,
2327 "onu-id": onuID,
2328 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002329 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002330 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002331 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002332 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002333 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002334 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002335
2336 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002337 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002338}
Girish Gowdra3d633032019-12-10 16:37:05 +05302339
Esin Karamanccb714b2019-11-29 15:02:06 +00002340// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002341func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002342 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002343 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302344 "classifier-info": classifierInfo,
2345 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002346
Esin Karaman65409d82020-03-18 10:58:18 +00002347 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002348 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002349 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002350 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002351
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002352 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002353
David K. Bainbridge794735f2020-02-11 21:01:37 -08002354 onuID := NoneOnuID
2355 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002356
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002357 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002358 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002359 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002360 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002361 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2362 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002363 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002364 }
2365 groupID := actionInfo[GroupID].(uint32)
2366 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002367 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002368 FlowType: Multicast,
2369 NetworkIntfId: int32(networkInterfaceID),
2370 GroupId: groupID,
2371 Classifier: classifierProto,
2372 Priority: int32(flow.Priority),
2373 Cookie: flow.Cookie}
2374
Kent Hagermane6ff1012020-07-14 15:07:53 -04002375 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002376 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002377 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002378 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002379 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002380 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002381 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002382 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002383 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002384 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002385 //cached group can be removed now
2386 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002387 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002388 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002389 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002390
David K. Bainbridge794735f2020-02-11 21:01:37 -08002391 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002392}
2393
Esin Karaman65409d82020-03-18 10:58:18 +00002394//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2395func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2396 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002397 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002398 if err != nil {
2399 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2400 }
2401 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002402 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002403
2404 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2405 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002406}
2407
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002408//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002409func (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 -07002410
Neha Sharma96b7bf22020-06-15 10:37:32 +00002411 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302412 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002413 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302414 log.Fields{
2415 "intf-id": intfID,
2416 "onu-id": onuID,
2417 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002418 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302419 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002420 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002421
Neha Sharma96b7bf22020-06-15 10:37:32 +00002422 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002423 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{
2424 UniId: uniID,
2425 TpInstancePath: tpPath,
2426 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
2427 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002428 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002429 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002430 tpDownloadMsg,
2431 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002432 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002433 onuDev.deviceType,
2434 onuDev.deviceID,
2435 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002436 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302437 return olterrors.NewErrCommunication("send-techprofile-download-request",
2438 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002439 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302440 "to-adapter": onuDev.deviceType,
2441 "onu-id": onuDev.deviceID,
2442 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002443 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002444 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302445 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302446}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002447
Girish Gowdra197acc12021-08-16 10:59:45 -07002448//AddOnuInfoToFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2449func (f *OpenOltFlowMgr) AddOnuInfoToFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302450
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002451 f.onuGemInfoLock.RLock()
2452 _, ok := f.onuGemInfoMap[onuID]
2453 f.onuGemInfoLock.RUnlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002454 // If the ONU already exists in onuGemInfo list, nothing to do
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002455 if ok {
2456 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2457 log.Fields{"onuID": onuID,
2458 "serialNum": serialNum})
2459 return nil
Girish Gowdra9602eb42020-09-09 15:50:39 -07002460 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002461
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002462 onuGemInfo := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2463 f.onuGemInfoLock.Lock()
2464 f.onuGemInfoMap[onuID] = &onuGemInfo
2465 f.onuGemInfoLock.Unlock()
2466 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onuID, onuGemInfo); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002467 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302468 }
Girish Gowdra197acc12021-08-16 10:59:45 -07002469 logger.Infow(ctx, "added-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302470 log.Fields{
2471 "intf-id": intfID,
2472 "onu-id": onuID,
2473 "serial-num": serialNum,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002474 "onu": onuGemInfo,
Shrey Baid26912972020-04-16 21:02:31 +05302475 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002476 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002477}
2478
Girish Gowdra197acc12021-08-16 10:59:45 -07002479//RemoveOnuInfoFromFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2480func (f *OpenOltFlowMgr) RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32) error {
2481
2482 f.onuGemInfoLock.Lock()
2483 delete(f.onuGemInfoMap, onuID)
2484 f.onuGemInfoLock.Unlock()
2485
2486 if err := f.resourceMgr.DelOnuGemInfo(ctx, intfID, onuID); err != nil {
2487 return err
2488 }
2489 logger.Infow(ctx, "deleted-onuinfo",
2490 log.Fields{
2491 "intf-id": intfID,
2492 "onu-id": onuID,
2493 "device-id": f.deviceHandler.device.Id})
2494 return nil
2495}
2496
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302497//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302498func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002499
Neha Sharma96b7bf22020-06-15 10:37:32 +00002500 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302501 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002502 "gem-port-id": gemPort,
2503 "intf-id": intfID,
2504 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002505 "device-id": f.deviceHandler.device.Id})
2506 f.onuGemInfoLock.RLock()
2507 onugem, ok := f.onuGemInfoMap[onuID]
2508 f.onuGemInfoLock.RUnlock()
2509 if !ok {
2510 logger.Warnw(ctx, "onu gem info is missing", log.Fields{
2511 "gem-port-id": gemPort,
2512 "intf-id": intfID,
2513 "onu-id": onuID,
2514 "device-id": f.deviceHandler.device.Id})
2515 return
2516 }
2517
2518 if onugem.OnuID == onuID {
2519 // check if gem already exists , else update the cache and kvstore
2520 for _, gem := range onugem.GemPorts {
2521 if gem == gemPort {
2522 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2523 log.Fields{
2524 "gem": gemPort,
2525 "device-id": f.deviceHandler.device.Id})
2526 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302527 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302528 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002529 onugem.GemPorts = append(onugem.GemPorts, gemPort)
2530 f.onuGemInfoLock.Lock()
2531 f.onuGemInfoMap[onuID] = onugem
2532 f.onuGemInfoLock.Unlock()
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002533 logger.Debugw(ctx, "updated onu gem info from cache", log.Fields{"onugem": onugem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002534 } else {
2535 logger.Warnw(ctx, "mismatched onu id", log.Fields{
2536 "gem-port-id": gemPort,
2537 "intf-id": intfID,
2538 "onu-id": onuID,
2539 "device-id": f.deviceHandler.device.Id})
2540 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302541 }
npujarec5762e2020-01-01 14:08:48 +05302542 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302543 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002544 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302545 log.Fields{
2546 "intf-id": intfID,
2547 "onu-id": onuID,
2548 "gemPort": gemPort,
2549 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002550 return
2551 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002552 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302553 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002554 "gem-port-id": gemPort,
2555 "intf-id": intfID,
2556 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002557 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002558}
2559
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002560//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302561func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002562 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002563
2564 if packetIn.IntfType == "pon" {
2565 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002566 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002567 onuID, uniID := packetIn.OnuId, packetIn.UniId
2568 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 +00002569
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002570 if packetIn.PortNo != 0 {
2571 logicalPortNum = packetIn.PortNo
2572 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002573 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002574 }
2575 // 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 +00002576 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002577 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002578 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002579 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002580
2581 if logger.V(log.DebugLevel) {
2582 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2583 log.Fields{
2584 "logical-port-num": logicalPortNum,
2585 "intf-type": packetIn.IntfType,
2586 "packet": hex.EncodeToString(packetIn.Pkt),
2587 })
2588 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002589 return logicalPortNum, nil
2590}
2591
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002592//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002593func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002594 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002595
2596 ctag, priority, err := getCTagFromPacket(ctx, packet)
2597 if err != nil {
2598 return 0, err
2599 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302600
Esin Karaman7fb80c22020-07-16 14:23:33 +00002601 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002602 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002603 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002604 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002605 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302606 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002607 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302608 log.Fields{
2609 "pktinkey": pktInkey,
2610 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002611
2612 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002613 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302614 //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 +00002615 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302616 if err == nil {
2617 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002618 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302619 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002620 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002621 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302622 log.Fields{
2623 "pktinkey": pktInkey,
2624 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302625 return gemPortID, nil
2626 }
2627 }
Shrey Baid26912972020-04-16 21:02:31 +05302628 return uint32(0), olterrors.NewErrNotFound("gem-port",
2629 log.Fields{
2630 "pktinkey": pktInkey,
2631 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002632
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002633}
2634
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002635func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2636 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002637 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002638 classifier[PacketTagType] = DoubleTag
2639 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002640 /* We manage flowId resource pool on per PON port basis.
2641 Since this situation is tricky, as a hack, we pass the NNI port
2642 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002643 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002644 on NNI port, use onu_id as -1 (invalid)
2645 ****************** CAVEAT *******************
2646 This logic works if the NNI Port Id falls within the same valid
2647 range of PON Port Ids. If this doesn't work for some OLT Vendor
2648 we need to have a re-look at this.
2649 *********************************************
2650 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002651 onuID := -1
2652 uniID := -1
2653 gemPortID := -1
2654 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002655 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302656 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302657 return olterrors.NewErrNotFound("nni-intreface-id",
2658 log.Fields{
2659 "classifier": classifier,
2660 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002661 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302662 }
2663
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002664 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002665 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002666 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002667 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002668
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002669 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2670 log.Fields{
2671 "classifier": classifier,
2672 "action": action,
2673 "flowId": logicalFlow.Id,
2674 "intf-id": networkInterfaceID})
2675
David K. Bainbridge794735f2020-02-11 21:01:37 -08002676 classifierProto, err := makeOpenOltClassifierField(classifier)
2677 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002678 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002679 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002680 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002681 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002682 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002683 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002684 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002685 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002686 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2687 OnuId: int32(onuID), // OnuId not required
2688 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002689 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002690 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002691 AllocId: int32(allocID), // AllocId not used
2692 NetworkIntfId: int32(networkInterfaceID),
2693 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002694 Classifier: classifierProto,
2695 Action: actionProto,
2696 Priority: int32(logicalFlow.Priority),
2697 Cookie: logicalFlow.Cookie,
2698 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002699 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002700 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002701 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002702 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002703 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002704}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002705
Esin Karamanae41e2b2019-12-17 18:13:13 +00002706//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2707func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2708 var packetType string
2709 ovid, ivid := false, false
2710 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2711 vid := vlanID & VlanvIDMask
2712 if vid != ReservedVlan {
2713 ovid = true
2714 }
2715 }
2716 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2717 vid := uint32(metadata)
2718 if vid != ReservedVlan {
2719 ivid = true
2720 }
2721 }
2722 if ovid && ivid {
2723 packetType = DoubleTag
2724 } else if !ovid && !ivid {
2725 packetType = Untagged
2726 } else {
2727 packetType = SingleTag
2728 }
2729 return packetType
2730}
2731
2732//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002733func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002734 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002735 action := make(map[string]interface{})
2736 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2737 action[TrapToHost] = true
2738 /* We manage flowId resource pool on per PON port basis.
2739 Since this situation is tricky, as a hack, we pass the NNI port
2740 index (network_intf_id) as PON port Index for the flowId resource
2741 pool. Also, there is no ONU Id available for trapping packets
2742 on NNI port, use onu_id as -1 (invalid)
2743 ****************** CAVEAT *******************
2744 This logic works if the NNI Port Id falls within the same valid
2745 range of PON Port Ids. If this doesn't work for some OLT Vendor
2746 we need to have a re-look at this.
2747 *********************************************
2748 */
2749 onuID := -1
2750 uniID := -1
2751 gemPortID := -1
2752 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002753 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002754 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302755 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002756 "classifier": classifier,
2757 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002758 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002759 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002760 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002761 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002762 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002763 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002764
David K. Bainbridge794735f2020-02-11 21:01:37 -08002765 classifierProto, err := makeOpenOltClassifierField(classifier)
2766 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002767 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002768 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002769 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002770 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002771 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002772 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002773 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002774 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002775 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2776 OnuId: int32(onuID), // OnuId not required
2777 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002778 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002779 FlowType: Downstream,
2780 AllocId: int32(allocID), // AllocId not used
2781 NetworkIntfId: int32(networkInterfaceID),
2782 GemportId: int32(gemPortID), // GemportId not used
2783 Classifier: classifierProto,
2784 Action: actionProto,
2785 Priority: int32(logicalFlow.Priority),
2786 Cookie: logicalFlow.Cookie,
2787 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002788 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002789 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002790 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002791 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002792
David K. Bainbridge794735f2020-02-11 21:01:37 -08002793 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002794}
2795
salmansiddiqui7ac62132019-08-22 03:58:50 +00002796func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2797 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302798 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002799 }
2800 if Dir == tp_pb.Direction_UPSTREAM {
2801 return "upstream", nil
2802 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2803 return "downstream", nil
2804 }
2805 return "", nil
2806}
2807
Kent Hagermane6ff1012020-07-14 15:07:53 -04002808// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302809func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002810 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002811 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002812 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002813 intfID := args[IntfID]
2814 onuID := args[OnuID]
2815 uniID := args[UniID]
2816 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002817 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002818 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002819 gemToAes := make(map[uint32]bool)
2820
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002821 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002822 var direction = tp_pb.Direction_UPSTREAM
2823 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002824 case *tp_pb.TechProfileInstance:
Gamze Abaka7650be62021-02-26 10:50:36 +00002825 if IsUpstream(actionInfo[Output].(uint32)) {
2826 attributes = TpInst.UpstreamGemPortAttributeList
2827 } else {
2828 attributes = TpInst.DownstreamGemPortAttributeList
2829 direction = tp_pb.Direction_DOWNSTREAM
2830 }
2831 default:
2832 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2833 return
2834 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002835
2836 if len(gemPorts) == 1 {
2837 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002838 gemPortID = gemPorts[0]
2839 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002840 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2841 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002842 pBitMap := attributes[idx].PbitMap
2843 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2844 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2845 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2846 // this pcp bit traffic.
2847 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2848 if pbitSet == pbit1 {
2849 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2850 pbitToGem[pcp] = gemID
2851 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002852 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002853 }
2854 }
2855 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002856 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2857 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2858 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002859 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002860 }
2861
Gamze Abaka7650be62021-02-26 10:50:36 +00002862 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2863 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2864
salmansiddiqui7ac62132019-08-22 03:58:50 +00002865 if ipProto, ok := classifierInfo[IPProto]; ok {
2866 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002867 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002868 "tp-id": tpID,
2869 "alloc-id": allocID,
2870 "intf-id": intfID,
2871 "onu-id": onuID,
2872 "uni-id": uniID,
2873 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002874 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002875 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002876 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002877 }
2878
Girish Gowdra32625212020-04-29 11:26:35 -07002879 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002880 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302881 log.Fields{
2882 "intf-id": intfID,
2883 "onu-id": onuID,
2884 "uni-id": uniID,
2885 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002886 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002887 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002888 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002889 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002890 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002891 return
2892 }
2893 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002894 if ethType.(uint32) == EapEthType {
2895 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002896 "intf-id": intfID,
2897 "onu-id": onuID,
2898 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002899 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002900 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002901 var vlanID uint32
2902 if val, ok := classifierInfo[VlanVid]; ok {
2903 vlanID = (val.(uint32)) & VlanvIDMask
2904 } else {
2905 vlanID = DefaultMgmtVlan
2906 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002907 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002908 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002909 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002910 } else if ethType.(uint32) == PPPoEDEthType {
2911 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2912 "tp-id": tpID,
2913 "alloc-id": allocID,
2914 "intf-id": intfID,
2915 "onu-id": onuID,
2916 "uni-id": uniID,
2917 })
2918 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002919 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002920 logger.Warn(ctx, err)
2921 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002922 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002923 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002924 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002925 "intf-id": intfID,
2926 "onu-id": onuID,
2927 "uni-id": uniID,
2928 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002929 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002930 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002931 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002932 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002933 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002934 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002935 "intf-id": intfID,
2936 "onu-id": onuID,
2937 "uni-id": uniID,
2938 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002939 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002940 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002941 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002942 }
2943 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002944 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302945 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002946 "intf-id": intfID,
2947 "onu-id": onuID,
2948 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302949 "classifier": classifierInfo,
2950 "action": actionInfo,
2951 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002952 return
2953 }
2954 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002955 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002956 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002957 logger.Warn(ctx, err)
2958 }
2959 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002960}
2961
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002962func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002963 f.gemToFlowIDsKey.RLock()
2964 flowIDList := f.gemToFlowIDs[gemPortID]
2965 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002966 return len(flowIDList) > 1
2967
Gamze Abakafee36392019-10-03 11:17:24 +00002968}
2969
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002970func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpInst *tp_pb.TechProfileInstance, gemPortID uint32) (bool, uint32) {
npujarec5762e2020-01-01 14:08:48 +05302971 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002972 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2973 for _, currentGemPort := range currentGemPorts {
2974 for _, tpGemPort := range tpGemPorts {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002975 if (currentGemPort == tpGemPort.GemportId) && (currentGemPort != gemPortID) {
Gamze Abakafee36392019-10-03 11:17:24 +00002976 return true, currentGemPort
2977 }
2978 }
2979 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002980 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
2981 return false, 0
2982}
Girish Gowdra54934262019-11-13 14:19:55 +05302983
Gamze Abakacb0e6772021-06-10 08:32:12 +00002984func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002985 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2986 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2987 tpInstances := f.techprofile.FindAllTpInstances(ctx, f.deviceHandler.device.Id, sq.tpID, sq.intfID, sq.onuID).([]tp_pb.TechProfileInstance)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002988 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302989 for i := 0; i < len(tpInstances); i++ {
2990 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00002991 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002992 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Gamze Abakacb0e6772021-06-10 08:32:12 +00002993 logger.Debugw(ctx, "alloc-is-in-use",
2994 log.Fields{
2995 "device-id": f.deviceHandler.device.Id,
2996 "intfID": sq.intfID,
2997 "onuID": sq.onuID,
2998 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002999 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00003000 })
3001 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303002 }
3003 }
3004 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003005 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003006}
3007
Neha Sharma96b7bf22020-06-15 10:37:32 +00003008func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003009 for _, field := range flows.GetOfbFields(flow) {
3010 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003011 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003012 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003013 } else if field.Type == flows.ETH_DST {
3014 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003015 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003016 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003017 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003018 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003019 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003020 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003021 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003022 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303023 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003024 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003025 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003026 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003027 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003028 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003029 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003030 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003031 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003032 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003033 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003034 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003035 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003036 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003037 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003038 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003039 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003040 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003041 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003042 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003043 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003044 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003045 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003046 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003047 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003048 return
3049 }
3050 }
3051}
3052
Neha Sharma96b7bf22020-06-15 10:37:32 +00003053func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003054 for _, action := range flows.GetActions(flow) {
3055 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003056 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003057 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003058 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003059 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003060 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003061 }
Scott Baker355d1742019-10-24 10:57:52 -07003062 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003063 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003064 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003065 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003066 if out := action.GetPush(); out != nil {
3067 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003068 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003069 } else {
3070 actionInfo[PushVlan] = true
3071 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003072 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303073 log.Fields{
3074 "push-tpid": actionInfo[TPID].(uint32),
3075 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003076 }
3077 }
Scott Baker355d1742019-10-24 10:57:52 -07003078 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003079 if out := action.GetSetField(); out != nil {
3080 if field := out.GetField(); field != nil {
3081 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003082 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003083 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003084 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3085 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003086 }
3087 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003088 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003089 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003090 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003091 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003092 }
3093 }
3094 return nil
3095}
3096
Neha Sharma96b7bf22020-06-15 10:37:32 +00003097func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003098 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003099 fieldtype := ofbField.GetType()
3100 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003101 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3102 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003103 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003104 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003105 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003106 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003107 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3108 pcp := ofbField.GetVlanPcp()
3109 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003110 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003111 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003112 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003113 }
3114 }
3115}
3116
Neha Sharma96b7bf22020-06-15 10:37:32 +00003117func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003118 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003119 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003120 } else {
3121 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003122 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003123 }
3124}
3125
Neha Sharma96b7bf22020-06-15 10:37:32 +00003126func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003127 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003128 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003129 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3130 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003131 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003132 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003133 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303134 log.Fields{
3135 "newinport": classifierInfo[InPort].(uint32),
3136 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003137 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303138 return olterrors.NewErrNotFound("child-in-port",
3139 log.Fields{
3140 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3141 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003142 }
3143 }
3144 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003145 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003146 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003147 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003148 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003149 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003150 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303151 log.Fields{
3152 "newoutport": actionInfo[Output].(uint32),
3153 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003154 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303155 return olterrors.NewErrNotFound("out-port",
3156 log.Fields{
3157 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3158 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003159 }
3160 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3161 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003162 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003163 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003164 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303165 log.Fields{
3166 "newinport": actionInfo[Output].(uint32),
3167 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003168 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303169 return olterrors.NewErrNotFound("nni-port",
3170 log.Fields{
3171 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3172 "in-port": classifierInfo[InPort].(uint32),
3173 "out-port": actionInfo[Output].(uint32),
3174 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003175 }
3176 }
3177 }
3178 return nil
3179}
Gamze Abakafee36392019-10-03 11:17:24 +00003180
Neha Sharma96b7bf22020-06-15 10:37:32 +00003181func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003182 /* Metadata 8 bytes:
3183 Most Significant 2 Bytes = Inner VLAN
3184 Next 2 Bytes = Tech Profile ID(TPID)
3185 Least Significant 4 Bytes = Port ID
3186 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3187 subscriber related flows.
3188 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003189 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003190 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003191 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003192 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003193 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003194 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003195}
3196
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003197func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3198 for _, sliceElement := range slice {
3199 if sliceElement == item {
3200 return slice
3201 }
3202 }
3203 return append(slice, item)
3204}
3205
3206func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003207 for _, sliceElement := range slice {
3208 if sliceElement == item {
3209 return slice
3210 }
3211 }
3212 return append(slice, item)
3213}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303214
3215// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003216func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303217
3218 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3219 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003220 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003221 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003222 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003223 log.Fields{
3224 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003225 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003226 return uint32(0), err
3227 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003228 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303229 return intfID, nil
3230 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003231 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003232 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003233 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003234 log.Fields{
3235 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003236 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003237 return uint32(0), err
3238 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003239 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303240 return intfID, nil
3241 }
3242 return uint32(0), nil
3243}
3244
3245// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003246func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3247 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3248 if err != nil {
3249 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3250 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3251 return
3252 }
3253 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003254
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003255 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003256 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003257 f.packetInGemPortLock.RUnlock()
3258
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303259 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003260 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003261 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 +05303262 log.Fields{
3263 "pktinkey": pktInkey,
3264 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003265 return
3266 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303267 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003268 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003269 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003270 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003271
npujarec5762e2020-01-01 14:08:48 +05303272 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003273 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 +05303274 log.Fields{
3275 "pktinkey": pktInkey,
3276 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303277}
3278
Esin Karaman7fb80c22020-07-16 14:23:33 +00003279//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3280func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3281 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003282 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003283 return 0, 0, errors.New("invalid packet length")
3284 }
3285 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3286 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3287
3288 var index int8
3289 if outerEthType == 0x8100 {
3290 if innerEthType == 0x8100 {
3291 // q-in-q 802.1ad or 802.1q double tagged packet.
3292 // get the inner vlanId
3293 index = 18
3294 } else {
3295 index = 14
3296 }
3297 priority := (packet[index] >> 5) & 0x7
3298 //13 bits composes vlanId value
3299 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3300 return vlan, priority, nil
3301 }
3302 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3303 return 0, 0, nil
3304}
3305
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003306func (f *OpenOltFlowMgr) loadFlowIDsForGemAndGemIDsForFlow(ctx context.Context) {
3307 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - start")
3308 f.onuGemInfoLock.RLock()
3309 f.gemToFlowIDsKey.Lock()
3310 f.flowIDToGemsLock.Lock()
3311 for _, og := range f.onuGemInfoMap {
3312 for _, gem := range og.GemPorts {
3313 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, f.ponPortIdx, gem)
3314 if err != nil {
3315 f.gemToFlowIDs[gem] = flowIDs
3316 for _, flowID := range flowIDs {
3317 if _, ok := f.flowIDToGems[flowID]; !ok {
3318 f.flowIDToGems[flowID] = []uint32{gem}
3319 } else {
3320 f.flowIDToGems[flowID] = appendUnique32bit(f.flowIDToGems[flowID], gem)
3321 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303322 }
3323 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303324 }
3325 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003326 f.flowIDToGemsLock.Unlock()
3327 f.gemToFlowIDsKey.Unlock()
3328 f.onuGemInfoLock.RUnlock()
3329 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - end")
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303330}
Esin Karamanccb714b2019-11-29 15:02:06 +00003331
Girish Gowdra9602eb42020-09-09 15:50:39 -07003332//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3333// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003334func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003335 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003336 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3337 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003338 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003339 "flow-id": flow.Id,
3340 "device-id": f.deviceHandler.device.Id})
3341 // Remove from device
3342 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3343 // DKB
3344 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3345 log.Fields{
3346 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003347 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003348 return err
3349 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003350
3351 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003352}
3353
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003354func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, ponID uint32, onuID uint32, uniID uint32) *ic.InterAdapterTechProfileDownloadMessage {
3355 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003356 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003357 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
3358 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003359 }
3360
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003361 switch tpInst := tpInst.(type) {
3362 case *tp_pb.TechProfileInstance:
3363 logger.Debugw(ctx, "fetched-tp-instance-successfully--formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
3364 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3365 TpInstancePath: tpPath,
3366 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003367 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003368 case *openoltpb2.EponTechProfileInstance:
3369 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3370 TpInstancePath: tpPath,
3371 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
3372 }
3373 default:
3374 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003375 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003376 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003377}
3378
Girish Gowdrabcf98af2021-07-01 08:24:42 -07003379func (f *OpenOltFlowMgr) getOnuGemInfoList(ctx context.Context) []rsrcMgr.OnuGemInfo {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003380 var onuGemInfoLst []rsrcMgr.OnuGemInfo
3381 f.onuGemInfoLock.RLock()
3382 defer f.onuGemInfoLock.RUnlock()
3383 for _, v := range f.onuGemInfoMap {
3384 onuGemInfoLst = append(onuGemInfoLst, *v)
3385 }
3386 return onuGemInfoLst
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003387}