blob: 7c3681e380c0d50fcedb33877b846342173813dd [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
Matteo Scandolo6056e822019-11-13 14:05:29 -080022 "encoding/hex"
Girish Gowdracefae192020-03-19 18:14:10 -070023 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "fmt"
Gamze Abaka7650be62021-02-26 10:50:36 +000025 "strconv"
serkant.uluderya4aff1862020-09-17 23:35:26 +030026 "strings"
27 "sync"
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070028 "time"
serkant.uluderya4aff1862020-09-17 23:35:26 +030029
khenaidoo106c61a2021-08-11 18:05:46 -040030 "github.com/opencord/voltha-lib-go/v7/pkg/meters"
Mahir Gunyel199570a2021-07-04 15:39:36 -070031
khenaidoo106c61a2021-08-11 18:05:46 -040032 "github.com/opencord/voltha-lib-go/v7/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070034 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040035 tp "github.com/opencord/voltha-lib-go/v7/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080036 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040037 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040038 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040039 ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
40 openoltpb2 "github.com/opencord/voltha-protos/v5/go/openolt"
41 tp_pb "github.com/opencord/voltha-protos/v5/go/tech_profile"
42 "github.com/opencord/voltha-protos/v5/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040043
Thomas Lee S94109f12020-03-03 16:39:29 +053044 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000045 "google.golang.org/grpc/codes"
46 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053047)
48
49const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070050 //IPProtoDhcp flow category
51 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Girish Gowdraa09aeab2020-09-14 16:30:52 -070053 //IgmpProto proto value
54 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070055
56 //EapEthType eapethtype value
57 EapEthType = 0x888e
58 //LldpEthType lldp ethtype value
59 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000060 //IPv4EthType IPv4 ethernet type value
61 IPv4EthType = 0x800
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030062 //PPPoEDEthType PPPoE discovery ethernet type value
63 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070064
Andrea Campanella7acc0b92020-02-14 09:20:49 +010065 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
66 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040067
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068 //DefaultMgmtVlan default vlan value
69 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053070
manikkaraj kbf256be2019-03-25 00:13:48 +053071 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070072
David K. Bainbridge82efc492019-09-04 09:57:11 -070073 //Upstream constant
74 Upstream = "upstream"
75 //Downstream constant
76 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000077 //Multicast constant
78 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070079 //PacketTagType constant
80 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070081 //Untagged constant
82 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070083 //SingleTag constant
84 SingleTag = "single_tag"
85 //DoubleTag constant
86 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053087
88 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089
90 //EthType constant
91 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000092 //EthDst constant
93 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070094 //TPID constant
95 TPID = "tpid"
96 //IPProto constant
97 IPProto = "ip_proto"
98 //InPort constant
99 InPort = "in_port"
100 //VlanVid constant
101 VlanVid = "vlan_vid"
102 //VlanPcp constant
103 VlanPcp = "vlan_pcp"
104
105 //UDPDst constant
106 UDPDst = "udp_dst"
107 //UDPSrc constant
108 UDPSrc = "udp_src"
109 //Ipv4Dst constant
110 Ipv4Dst = "ipv4_dst"
111 //Ipv4Src constant
112 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700113 //Metadata constant
114 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700115 //TunnelID constant
116 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700117 //Output constant
118 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000119 //GroupID constant
120 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700121 // Actions
122
123 //PopVlan constant
124 PopVlan = "pop_vlan"
125 //PushVlan constant
126 PushVlan = "push_vlan"
127 //TrapToHost constant
128 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400129 //MaxMeterBand constant
130 MaxMeterBand = 2
131 //VlanPCPMask contant
132 VlanPCPMask = 0xFF
133 //VlanvIDMask constant
134 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000135 //IntfID constant
136 IntfID = "intfId"
137 //OnuID constant
138 OnuID = "onuId"
139 //UniID constant
140 UniID = "uniId"
141 //PortNo constant
142 PortNo = "portNo"
143 //AllocID constant
144 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000145 //GemID constant
146 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000147
148 //NoneOnuID constant
149 NoneOnuID = -1
150 //NoneUniID constant
151 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700152
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700153 // Max number of flows that can be queued per ONU
154 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530155
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700156 bitMapPrefix = "0b"
157 pbit1 = '1'
158)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400159
Gamze Abakafee36392019-10-03 11:17:24 +0000160type schedQueue struct {
161 direction tp_pb.Direction
162 intfID uint32
163 onuID uint32
164 uniID uint32
165 tpID uint32
166 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700167 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000168 meterID uint32
khenaidoodc2116e2021-10-19 17:33:19 -0400169 flowMetadata *ofp.FlowMetadata
Gamze Abakafee36392019-10-03 11:17:24 +0000170}
171
Gamze Abaka7650be62021-02-26 10:50:36 +0000172type flowContext struct {
173 intfID uint32
174 onuID uint32
175 uniID uint32
176 portNo uint32
177 classifier map[string]interface{}
178 action map[string]interface{}
179 logicalFlow *ofp.OfpFlowStats
180 allocID uint32
181 gemPortID uint32
182 tpID uint32
183 pbitToGem map[uint32]uint32
184 gemToAes map[uint32]bool
185}
186
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700187// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
188// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
189// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
190// flow and processes it serially
191type flowControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400192 ctx context.Context // Flow handler context
193 addFlow bool // if true flow to be added, else removed
194 flow *ofp.OfpFlowStats // Flow message
195 flowMetadata *ofp.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
196 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000197}
198
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700199//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530200type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700201 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700202 techprofile tp.TechProfileIf
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700203 deviceHandler *DeviceHandler
204 grpMgr *OpenOltGroupMgr
205 resourceMgr *rsrcMgr.OpenOltResourceMgr
206
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700207 gemToFlowIDs map[uint32][]uint64 // gem port id to flow ids
208 gemToFlowIDsKey sync.RWMutex // lock to be used to access the gemToFlowIDs map
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700209
210 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
211 packetInGemPortLock sync.RWMutex
212
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700213 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700214 onuGemInfoMap map[uint32]*rsrcMgr.OnuGemInfo //onu, gem and uni info local cache -> map of onuID to OnuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700215 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700216 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700217
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700218 flowIDToGems map[uint64][]uint32
219 flowIDToGemsLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700220
221 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
222 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700223 incomingFlows []chan flowControlBlock
224 stopFlowHandlerRoutine []chan bool
225 flowHandlerRoutineActive []bool
manikkaraj kbf256be2019-03-25 00:13:48 +0530226}
227
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700228//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700229func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000230 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530231 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530232 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530233
manikkaraj kbf256be2019-03-25 00:13:48 +0530234 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700235 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700236 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530237 flowMgr.resourceMgr = rMgr
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700238 if err = flowMgr.populateTechProfileForCurrentPonPort(ctx); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700239 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530240 return nil
241 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700242 flowMgr.gemToFlowIDs = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530243 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700244 flowMgr.flowIDToGems = make(map[uint64][]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700245
246 // Create a slice of buffered channels for handling concurrent flows per ONU.
247 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700248 flowMgr.incomingFlows = make([]chan flowControlBlock, plt.MaxOnusPerPon+1)
249 flowMgr.stopFlowHandlerRoutine = make([]chan bool, plt.MaxOnusPerPon+1)
250 flowMgr.flowHandlerRoutineActive = make([]bool, plt.MaxOnusPerPon+1)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700251 for i := range flowMgr.incomingFlows {
252 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
Girish Gowdraae56c722021-11-22 14:31:11 -0800253 flowMgr.stopFlowHandlerRoutine[i] = make(chan bool)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700254 // Spin up a go routine to handling incoming flows (add/remove).
255 // There will be on go routine per ONU.
256 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700257 flowMgr.flowHandlerRoutineActive[i] = true
258 go flowMgr.perOnuFlowHandlerRoutine(i, flowMgr.incomingFlows[i], flowMgr.stopFlowHandlerRoutine[i])
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700259 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700260 flowMgr.onuGemInfoMap = make(map[uint32]*rsrcMgr.OnuGemInfo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530261 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700262 onuIDStart := flowMgr.deviceHandler.deviceInfo.OnuIdStart
263 onuIDEnd := flowMgr.deviceHandler.deviceInfo.OnuIdEnd
264 for onuID := onuIDStart; onuID <= onuIDEnd; onuID++ {
265 // check for a valid serial number in onuGem as GetOnuGemInfo can return nil error in case of nothing found in the path.
Gamze Abaka6f345c12021-09-08 01:14:33 +0000266 onugem, err := rMgr.GetOnuGemInfo(ctx, ponPortIdx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700267 if err == nil && onugem != nil && onugem.SerialNumber != "" {
268 flowMgr.onuGemInfoMap[onuID] = onugem
269 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530270 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700271
272 //Load flowID list per gem map And gemIDs per flow per interface from the kvstore.
273 flowMgr.loadFlowIDsForGemAndGemIDsForFlow(ctx)
274
Esin Karamanccb714b2019-11-29 15:02:06 +0000275 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700276 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000277 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530278 return &flowMgr
279}
280
Kent Hagermane6ff1012020-07-14 15:07:53 -0400281func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700282 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
283 // Flow is not replicated in this case, we need to register the flow for a single gem-port
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700284 return f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700285 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
286 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
287 for _, gemPort := range deviceFlow.PbitToGemport {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700288 if err := f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700289 return err
290 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700291 }
Gamze Abakafee36392019-10-03 11:17:24 +0000292 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700293 return nil
294}
295
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700296func (f *OpenOltFlowMgr) registerFlowIDForGemAndGemIDForFlow(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
297 // update gem->flows map
298 f.gemToFlowIDsKey.Lock()
299 flowIDList, ok := f.gemToFlowIDs[gemPortID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700300 if !ok {
301 flowIDList = []uint64{flowFromCore.Id}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700302 } else {
303 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700304 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700305 f.gemToFlowIDs[gemPortID] = flowIDList
306 f.gemToFlowIDsKey.Unlock()
307
308 // update flow->gems map
309 f.flowIDToGemsLock.Lock()
310 if _, ok := f.flowIDToGems[flowFromCore.Id]; !ok {
311 f.flowIDToGems[flowFromCore.Id] = []uint32{gemPortID}
312 } else {
313 f.flowIDToGems[flowFromCore.Id] = appendUnique32bit(f.flowIDToGems[flowFromCore.Id], gemPortID)
314 }
315 f.flowIDToGemsLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700316
317 // update the flowids for a gem to the KVstore
318 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400319}
320
Girish Gowdra9602eb42020-09-09 15:50:39 -0700321func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000322 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
khenaidoodc2116e2021-10-19 17:33:19 -0400323 UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000324 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530325 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700326 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530327
Neha Sharma96b7bf22020-06-15 10:37:32 +0000328 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530329 "device-id": f.deviceHandler.device.Id,
330 "intf-id": intfID,
331 "onu-id": onuID,
332 "uni-id": uniID,
333 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700334 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530335 "action": actionInfo,
336 "usmeter-iD": UsMeterID,
337 "dsmeter-iD": DsMeterID,
338 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400339 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
340 // is because the flow is an NNI flow and there would be no onu resources associated with it
341 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400342 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200343 cause := "no-onu-id-for-flow"
344 fields := log.Fields{
345 "onu": onuID,
346 "port-no": portNo,
347 "classifer": classifierInfo,
348 "action": actionInfo,
349 "device-id": f.deviceHandler.device.Id}
350 logger.Errorw(ctx, cause, fields)
351 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530352 }
353
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700354 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000355 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530356 "uni": uni,
357 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530358
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700359 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
360 "device-id": f.deviceHandler.device.Id,
361 "intf-id": intfID,
362 "onu-id": onuID,
363 "uni-id": uniID,
364 "port-no": portNo,
365 "classifier": classifierInfo,
366 "action": actionInfo,
367 "usmeter-id": UsMeterID,
368 "dsmeter-id": DsMeterID,
369 "tp-id": TpID})
370 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
371 if allocID == 0 || gemPorts == nil || TpInst == nil {
372 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
373 return olterrors.NewErrNotFound(
374 "alloc-id-gem-ports-tp-unavailable",
375 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400376 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700377 args := make(map[string]uint32)
378 args[IntfID] = intfID
379 args[OnuID] = onuID
380 args[UniID] = uniID
381 args[PortNo] = portNo
382 args[AllocID] = allocID
383
384 /* Flows can be added specific to gemport if p-bits are received.
385 * If no pbit mentioned then adding flows for all gemports
386 */
Gamze Abaka6d0a64f2021-11-18 08:08:33 +0000387 return f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530388}
389
salmansiddiqui7ac62132019-08-22 03:58:50 +0000390// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530391func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400392
Neha Sharma96b7bf22020-06-15 10:37:32 +0000393 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530394 log.Fields{"dir": sq.direction,
395 "intf-id": sq.intfID,
396 "onu-id": sq.onuID,
397 "uni-id": sq.uniID,
398 "tp-id": sq.tpID,
399 "meter-id": sq.meterID,
400 "tp-inst": sq.tpInst,
401 "flowmetadata": sq.flowMetadata,
402 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400403
Gamze Abakafee36392019-10-03 11:17:24 +0000404 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000405 if err != nil {
406 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400407 }
408
409 /* Lets make a simple assumption that if the meter-id is present on the KV store,
410 * then the scheduler and queues configuration is applied on the OLT device
411 * in the given direction.
412 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000413
Manikkaraj kb1d51442019-07-23 10:41:02 -0400414 var SchedCfg *tp_pb.SchedulerConfig
Girish Gowdraa482f272021-03-24 23:04:19 -0700415 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400416 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530417 return olterrors.NewErrNotFound("meter",
418 log.Fields{"intf-id": sq.intfID,
419 "onu-id": sq.onuID,
420 "uni-id": sq.uniID,
421 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400422 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000423
Girish Gowdraa482f272021-03-24 23:04:19 -0700424 if meterInfo != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +0000425 // If RefCnt become 0 clear the meter information from the DB.
426 if meterInfo.MeterID != sq.meterID && meterInfo.RefCnt == 0 {
427 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID); err != nil {
Girish Gowdraa482f272021-03-24 23:04:19 -0700428 return err
429 }
Gamze Abaka745ccb72021-11-18 11:29:58 +0000430 } else {
431 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id, "meter-id": sq.meterID})
432 if meterInfo.MeterID == sq.meterID {
433 return f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true)
434 }
435 return olterrors.NewErrInvalidValue(log.Fields{
436 "unsupported": "meter-id",
437 "kv-store-meter-id": meterInfo.MeterID,
438 "meter-id-in-flow": sq.meterID,
439 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400440 }
441 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000442
Neha Sharma96b7bf22020-06-15 10:37:32 +0000443 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530444 log.Fields{
445 "meter-id": sq.meterID,
446 "direction": Direction,
447 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000448
Gamze Abakafee36392019-10-03 11:17:24 +0000449 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700450 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Gamze Abakafee36392019-10-03 11:17:24 +0000451 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700452 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Girish Kumar8f73fe02019-12-09 13:19:37 +0000453 }
454
Girish Gowdraa482f272021-03-24 23:04:19 -0700455 found := false
456 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000457 if sq.flowMetadata != nil {
458 for _, meter := range sq.flowMetadata.Meters {
459 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700460 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700461 meterInfo.RefCnt = 1 // initialize it to 1, since this is the first flow that referenced the meter id.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000462 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700463 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530464 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700465 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400466 break
467 }
468 }
469 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000470 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400471 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700472 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530473 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800474 "reason": "Could-not-get-meterbands-from-flowMetadata",
475 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530476 "meter-id": sq.meterID,
477 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478 }
Gamze Abaka01174422021-03-10 06:55:27 +0000479
480 var TrafficShaping *tp_pb.TrafficShapingInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700481 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
Gamze Abaka01174422021-03-10 06:55:27 +0000482 return olterrors.NewErrInvalidValue(log.Fields{
483 "reason": "invalid-meter-config",
484 "meter-id": sq.meterID,
485 "device-id": f.deviceHandler.device.Id}, nil)
486 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400487
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700488 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000489 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400490
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700491 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530492 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
493 log.Fields{"intf-id": sq.intfID,
494 "direction": sq.direction,
495 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400496 }
497
salmansiddiqui7ac62132019-08-22 03:58:50 +0000498 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400499 * store the meter id on the KV store, for further reference.
500 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700501 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 +0530502 return olterrors.NewErrAdapter("failed-updating-meter-id",
503 log.Fields{"onu-id": sq.onuID,
504 "meter-id": sq.meterID,
505 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400506 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000507 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530508 log.Fields{"direction": Direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700509 "meter-info": meterInfo,
510 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400511 return nil
512}
513
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700514func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700515 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000516
517 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530518 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
519 log.Fields{"intf-id": sq.intfID,
520 "direction": sq.direction,
521 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000522 }
523
Gamze Abakacb0e6772021-06-10 08:32:12 +0000524 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
525 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
526 log.Fields{
527 "direction": sq.direction,
528 "TrafficScheds": TrafficSched,
529 "device-id": f.deviceHandler.device.Id,
530 "intfID": sq.intfID,
531 "onuID": sq.onuID,
532 "uniID": sq.uniID})
533 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
534 IntfId: sq.intfID, OnuId: sq.onuID,
535 UniId: sq.uniID, PortNo: sq.uniPort,
536 TrafficScheds: TrafficSched}); err != nil {
537 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
538 }
539 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
540 "direction": sq.direction,
541 "traffic-queues": trafficQueues,
542 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000543 }
544
545 // On receiving the CreateTrafficQueues request, the driver should create corresponding
546 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000547 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530548 log.Fields{"direction": sq.direction,
549 "traffic-queues": trafficQueues,
550 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530551 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000552 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
553 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000554 TrafficQueues: trafficQueues,
555 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530556 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000557 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000558 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530559 "direction": sq.direction,
560 "traffic-queues": trafficQueues,
561 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000562
Esin Karamanccb714b2019-11-29 15:02:06 +0000563 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700564 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000565 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700566 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 +0000567 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
568 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000569 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000570 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700571 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000572 gemPortID: multicastQueuePerPonPort.GemportId,
573 servicePriority: multicastQueuePerPonPort.Priority,
574 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700575 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000576 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400577 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700578 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400579 return err
580 }
Shrey Baid26912972020-04-16 21:02:31 +0530581
Neha Sharma96b7bf22020-06-15 10:37:32 +0000582 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000583 }
584 }
585 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000586 return nil
587}
588
salmansiddiqui7ac62132019-08-22 03:58:50 +0000589// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530590func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400591
592 var Direction string
593 var SchedCfg *tp_pb.SchedulerConfig
594 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000595 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530596 log.Fields{
597 "direction": sq.direction,
598 "intf-id": sq.intfID,
599 "onu-id": sq.onuID,
600 "uni-id": sq.uniID,
601 "uni-port": sq.uniPort,
602 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000603 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700604 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400605 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000606 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700607 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400608 Direction = "downstream"
609 }
610
Girish Gowdraa482f272021-03-24 23:04:19 -0700611 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 -0400612
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700613 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000614 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000615
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700616 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000617 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530618 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
619 log.Fields{
620 "intf-id": sq.intfID,
621 "direction": sq.direction,
622 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000623 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400624
npujarec5762e2020-01-01 14:08:48 +0530625 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000626 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
627 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000628 TrafficQueues: TrafficQueues,
629 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000630 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530631 log.Fields{
632 "intf-id": sq.intfID,
633 "traffic-queues": TrafficQueues,
634 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400635 }
Gamze Abakacb0e6772021-06-10 08:32:12 +0000636 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400637
Gamze Abakacb0e6772021-06-10 08:32:12 +0000638 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
639 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
640 IntfId: sq.intfID, OnuId: sq.onuID,
641 UniId: sq.uniID, PortNo: sq.uniPort,
642 TrafficScheds: TrafficSched}); err != nil {
643 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
644 log.Fields{
645 "intf-id": sq.intfID,
646 "traffic-schedulers": TrafficSched,
647 "onu-id": sq.onuID,
648 "uni-id": sq.uniID,
649 "uni-port": sq.uniPort}, err)
650 }
651
652 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
653 log.Fields{"device-id": f.deviceHandler.device.Id,
654 "intf-id": sq.intfID,
655 "onu-id": sq.onuID,
656 "uni-id": sq.uniID,
657 "uni-port": sq.uniPort})
658
659 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700660 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
Gamze Abakacb0e6772021-06-10 08:32:12 +0000661 // Delete the TCONT on the ONU.
662 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
663 tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
664 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
665 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
666 log.Fields{
667 "intf": sq.intfID,
668 "onu-id": sq.onuID,
669 "uni-id": sq.uniID,
670 "device-id": f.deviceHandler.device.Id,
671 "alloc-id": allocID})
672 }
673 }
674 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000675
676 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400677 * delete the meter id on the KV store.
678 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700679 err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400680 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530681 return olterrors.NewErrAdapter("unable-to-remove-meter",
682 log.Fields{
683 "onu": sq.onuID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700684 "device-id": f.deviceHandler.device.Id,
685 "intf-id": sq.intfID,
686 "onu-id": sq.onuID,
687 "uni-id": sq.uniID,
688 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400689 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000690 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530691 log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530692 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700693 "device-id": f.deviceHandler.device.Id,
694 "intf-id": sq.intfID,
695 "onu-id": sq.onuID,
696 "uni-id": sq.uniID,
697 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400698 return err
699}
700
Girish Gowdra197acc12021-08-16 10:59:45 -0700701// We are trying to force remove the schedulers and queues here if one exists for the given key.
702// We ignore any errors encountered in the process. The errors most likely are encountered when
703// the schedulers and queues are already cleared for the given key.
704func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
705
706 var schedCfg *tp_pb.SchedulerConfig
707 var err error
708 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
709 log.Fields{
710 "direction": sq.direction,
711 "intf-id": sq.intfID,
712 "onu-id": sq.onuID,
713 "uni-id": sq.uniID,
714 "uni-port": sq.uniPort,
715 "tp-id": sq.tpID,
716 "device-id": f.deviceHandler.device.Id})
717 if sq.direction == tp_pb.Direction_UPSTREAM {
718 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
719 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
720 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
721 }
722
723 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
724 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
725 TrafficSched[0].TechProfileId = sq.tpID
726
727 // Remove traffic queues. Ignore any errors, just log them.
728 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
729 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
730 "direction": sq.direction,
731 "intf-id": sq.intfID,
732 "onu-id": sq.onuID,
733 "uni-id": sq.uniID,
734 "uni-port": sq.uniPort,
735 "tp-id": sq.tpID,
736 "device-id": f.deviceHandler.device.Id,
737 "err": err})
738 } else {
739 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
740 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
741 UniId: sq.uniID, PortNo: sq.uniPort,
742 TrafficQueues: TrafficQueues,
743 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
744 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
745 "direction": sq.direction,
746 "intf-id": sq.intfID,
747 "onu-id": sq.onuID,
748 "uni-id": sq.uniID,
749 "uni-port": sq.uniPort,
750 "tp-id": sq.tpID,
751 "device-id": f.deviceHandler.device.Id,
752 "err": err})
753
754 } else {
755 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
756 "direction": sq.direction,
757 "intf-id": sq.intfID,
758 "onu-id": sq.onuID,
759 "uni-id": sq.uniID,
760 "uni-port": sq.uniPort,
761 "tp-id": sq.tpID})
762 }
763 }
764
765 // Remove traffic schedulers. Ignore any errors, just log them.
766 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
767 IntfId: sq.intfID, OnuId: sq.onuID,
768 UniId: sq.uniID, PortNo: sq.uniPort,
769 TrafficScheds: TrafficSched}); err != nil {
770 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
771 "direction": sq.direction,
772 "intf-id": sq.intfID,
773 "onu-id": sq.onuID,
774 "uni-id": sq.uniID,
775 "uni-port": sq.uniPort,
776 "tp-id": sq.tpID,
777 "device-id": f.deviceHandler.device.Id,
778 "err": err})
779 } else {
780 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
781 "direction": sq.direction,
782 "intf-id": sq.intfID,
783 "onu-id": sq.onuID,
784 "uni-id": sq.uniID,
785 "uni-port": sq.uniPort,
786 "tp-id": sq.tpID})
787 }
788}
789
Gamze Abakafee36392019-10-03 11:17:24 +0000790// This function allocates tconts and GEM ports for an ONU
khenaidoodc2116e2021-10-19 17:33:19 -0400791func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) (uint32, []uint32, interface{}) {
Gamze Abakafee36392019-10-03 11:17:24 +0000792 var allocIDs []uint32
793 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530794 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530795 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000796 var err error
npujarec5762e2020-01-01 14:08:48 +0530797 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
798 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000799 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530800
Neha Sharma96b7bf22020-06-15 10:37:32 +0000801 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530802 "intf-id": intfID,
803 "onu-id": onuID,
804 "uni-id": uniID,
805 "device-id": f.deviceHandler.device.Id,
806 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530807
Manikkaraj kb1d51442019-07-23 10:41:02 -0400808 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700809 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000810 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000811 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530812 log.Fields{
813 "path": tpPath,
814 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700815 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000816 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530817 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000818 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530819 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700820 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530821 "tp-id": TpID,
822 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000823 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530824 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400825 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700826 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400827 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530828 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000829 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530830 log.Fields{
831 "uni": uni,
832 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530833 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530834 }
Gamze Abakafee36392019-10-03 11:17:24 +0000835
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700836 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700837 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700838 if UsMeterID != 0 {
839 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
840 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
841 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000842 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700843 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700844 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700845 "onu-id": onuID,
846 "uni-id": uniID,
847 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700848 "meter-id": UsMeterID,
849 "device-id": f.deviceHandler.device.Id})
850 return 0, nil, nil
851 }
852 }
853 if DsMeterID != 0 {
854 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
855 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
856 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000857 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700858 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700859 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700860 "onu-id": onuID,
861 "uni-id": uniID,
862 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700863 "meter-id": DsMeterID,
864 "device-id": f.deviceHandler.device.Id})
865 return 0, nil, nil
866 }
867 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700868 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700869 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700870 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700871 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700872 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000873
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700874 if tpInstanceExists {
875 return allocID, gemPortIDs, techProfileInstance
876 }
877
878 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700879 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700880 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000881 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700882 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700883 "intf-id": intfID,
884 "onu-id": onuID,
885 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700886 "alloc-ids": allocIDs,
887 "gemports": allgemPortIDs,
888 "device-id": f.deviceHandler.device.Id})
889 // Send Tconts and GEM ports to KV store
890 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530891 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400892 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700893 // CreateSchedulerQueues for EPON needs to be implemented here
894 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700895 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700896 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700897 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700898 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700899 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700900
901 if tpInstanceExists {
902 return allocID, gemPortIDs, techProfileInstance
903 }
904
905 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700906 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700907 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000908 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700909 log.Fields{
910 "alloc-ids": allocIDs,
911 "gemports": allgemPortIDs,
912 "device-id": f.deviceHandler.device.Id})
913 // Send Tconts and GEM ports to KV store
914 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
915 return allocID, gemPortIDs, techProfileInstance
916 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000917 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700918 log.Fields{
919 "tpInst": tpInst})
920 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530921 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530922}
923
npujarec5762e2020-01-01 14:08:48 +0530924func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530925
Neha Sharma96b7bf22020-06-15 10:37:32 +0000926 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530927 log.Fields{
928 "intf-id": intfID,
929 "onu-id": onuID,
930 "uni-id": uniID,
931 "alloc-id": allocID,
932 "gemport-ids": gemPortIDs,
933 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530934 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530935 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000936 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 +0530937 }
npujarec5762e2020-01-01 14:08:48 +0530938 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000939 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 +0530940 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700941
Neha Sharma96b7bf22020-06-15 10:37:32 +0000942 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 -0400943 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530944 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400945 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530946}
947
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700948func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530949 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000950 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700951 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
952 var err error
953 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
954 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
955 if err != nil || f.techprofile == nil {
956 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
957 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
958 }
959 logger.Debugw(ctx, "init-tech-profile-done",
960 log.Fields{
961 "intf-id": intfID,
962 "device-id": f.deviceHandler.device.Id})
963 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700964 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530965 }
966 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700967 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
968 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 +0530969}
970
Gamze Abaka7650be62021-02-26 10:50:36 +0000971func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Andrea Campanellafaa42152021-10-28 11:50:56 +0530972 flowContext.classifier[PacketTagType] = SingleTag // FIXME: This hardcoding needs to be removed.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000973 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530974 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000975 "uplinkClassifier": flowContext.classifier,
976 "uplinkAction": flowContext.action})
977 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530978 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530979}
980
Gamze Abaka7650be62021-02-26 10:50:36 +0000981func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
982 downlinkClassifier := flowContext.classifier
983 downlinkAction := flowContext.action
984
Andrea Campanellafaa42152021-10-28 11:50:56 +0530985 // TODO: For now mark the PacketTagType as SingleTag when OLT is transparent to VLAN
986 // Per some deployment models, it is also possible that ONU operates on double tagged packets,
987 // so this hardcoding of SingeTag packet-tag-type may be problem for such deployment models.
988 // Need a better way for detection of packet tag type from OpenFlow message.
989 if _, ok := downlinkClassifier[VlanVid]; !ok {
990 downlinkClassifier[PacketTagType] = SingleTag
991 } else {
992 downlinkClassifier[PacketTagType] = DoubleTag
993 downlinkAction[PopVlan] = true
994 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000995 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530996 log.Fields{
997 "downlinkClassifier": downlinkClassifier,
998 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400999 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
1000 if vlan, exists := downlinkClassifier[VlanVid]; exists {
1001 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -07001002 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001003 if uint32(metadata.(uint64)) == plt.MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001004 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301005 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001006 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301007 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +00001008 "onu-id": flowContext.onuID,
1009 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001010 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -04001011 }
1012 }
1013 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301014 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001015
Matt Jeannereted16b7c2019-11-01 13:31:35 -04001016 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1017 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +05301018 if ok {
1019 downlinkAction[VlanVid] = dlClVid & 0xfff
Girish Gowdra26f344b2019-10-23 14:39:13 +05301020 }
1021
Gamze Abaka7650be62021-02-26 10:50:36 +00001022 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301023}
1024
Gamze Abaka7650be62021-02-26 10:50:36 +00001025func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001026
Gamze Abaka7650be62021-02-26 10:50:36 +00001027 intfID := flowContext.intfID
1028 onuID := flowContext.onuID
1029 uniID := flowContext.uniID
1030 classifier := flowContext.classifier
1031 action := flowContext.action
1032 allocID := flowContext.allocID
1033 gemPortID := flowContext.gemPortID
1034 tpID := flowContext.tpID
1035 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001036 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301037 log.Fields{
1038 "intf-id": intfID,
1039 "onu-id": onuID,
1040 "uni-id": uniID,
1041 "device-id": f.deviceHandler.device.Id,
1042 "classifier": classifier,
1043 "action": action,
1044 "direction": direction,
1045 "alloc-id": allocID,
1046 "gemport-id": gemPortID,
1047 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001048
1049 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001050 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301051 log.Fields{
1052 "device-id": f.deviceHandler.device.Id,
1053 "intf-id": intfID,
1054 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001055 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301056 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001057 classifierProto, err := makeOpenOltClassifierField(classifier)
1058 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301059 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301060 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001061 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301062 log.Fields{
1063 "classifier": *classifierProto,
1064 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001065 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001066 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301067 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301068 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001069 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301070 log.Fields{
1071 "action": *actionProto,
1072 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001073 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301074 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301075 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001076 log.Fields{
1077 "classifier": classifier,
1078 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301079 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001080 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301081 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001082
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001083 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001084 OnuId: int32(onuID),
1085 UniId: int32(uniID),
1086 FlowId: logicalFlow.Id,
1087 FlowType: direction,
1088 AllocId: int32(allocID),
1089 NetworkIntfId: int32(networkIntfID),
1090 GemportId: int32(gemPortID),
1091 Classifier: classifierProto,
1092 Action: actionProto,
1093 Priority: int32(logicalFlow.Priority),
1094 Cookie: logicalFlow.Cookie,
1095 PortNo: flowContext.portNo,
1096 TechProfileId: tpID,
1097 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1098 PbitToGemport: flowContext.pbitToGem,
1099 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001100 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001101 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001102 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301103 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001104 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301105 log.Fields{"direction": direction,
1106 "device-id": f.deviceHandler.device.Id,
1107 "flow": flow,
1108 "intf-id": intfID,
1109 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001110
David K. Bainbridge794735f2020-02-11 21:01:37 -08001111 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301112}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001113
Gamze Abaka7650be62021-02-26 10:50:36 +00001114func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1115
1116 intfID := flowContext.intfID
1117 onuID := flowContext.onuID
1118 uniID := flowContext.uniID
1119 logicalFlow := flowContext.logicalFlow
1120 classifier := flowContext.classifier
1121 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301122
Neha Sharma96b7bf22020-06-15 10:37:32 +00001123 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301124 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301125 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001126 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301127 "action": action,
1128 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001129 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301130 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301131
1132 // Clear the action map
1133 for k := range action {
1134 delete(action, k)
1135 }
1136
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001137 action[TrapToHost] = true
1138 classifier[UDPSrc] = uint32(68)
1139 classifier[UDPDst] = uint32(67)
1140 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301141
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001142 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001143 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301144 log.Fields{
1145 "device-id": f.deviceHandler.device.Id,
1146 "intf-id": intfID,
1147 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001148 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301149 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301150
Neha Sharma96b7bf22020-06-15 10:37:32 +00001151 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301152 log.Fields{
1153 "ul_classifier": classifier,
1154 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001155 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301156 "intf-id": intfID,
1157 "onu-id": onuID,
1158 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301159
David K. Bainbridge794735f2020-02-11 21:01:37 -08001160 classifierProto, err := makeOpenOltClassifierField(classifier)
1161 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301162 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301163 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001164 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001165 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001166 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301167 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301168 }
1169
David K. Bainbridge794735f2020-02-11 21:01:37 -08001170 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001171 OnuId: int32(onuID),
1172 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001173 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001174 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001175 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001176 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001177 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301178 Classifier: classifierProto,
1179 Action: actionProto,
1180 Priority: int32(logicalFlow.Priority),
1181 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001182 PortNo: flowContext.portNo,
1183 TechProfileId: flowContext.tpID,
1184 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1185 PbitToGemport: flowContext.pbitToGem,
1186 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001187 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001188 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001189 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001190 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001191 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301192 log.Fields{
1193 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001194 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301195 "intf-id": intfID,
1196 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301197
David K. Bainbridge794735f2020-02-11 21:01:37 -08001198 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301199}
1200
Esin Karamanae41e2b2019-12-17 18:13:13 +00001201//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001202func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1203 delete(flowContext.classifier, VlanVid)
1204 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001205}
1206
1207//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001208func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1209
1210 intfID := flowContext.intfID
1211 onuID := flowContext.onuID
1212 uniID := flowContext.uniID
1213 logicalFlow := flowContext.logicalFlow
1214 classifier := flowContext.classifier
1215 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001216
Neha Sharma96b7bf22020-06-15 10:37:32 +00001217 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001218 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301219 return olterrors.NewErrNotFound("nni-interface-id",
1220 log.Fields{
1221 "classifier": classifier,
1222 "action": action,
1223 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001224 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001225 }
1226
1227 // Clear the action map
1228 for k := range action {
1229 delete(action, k)
1230 }
1231
1232 action[TrapToHost] = true
1233 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001234
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001235 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001236 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001237 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001238 }
1239
Neha Sharma96b7bf22020-06-15 10:37:32 +00001240 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301241 log.Fields{
1242 "ul_classifier": classifier,
1243 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001244 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301245 "device-id": f.deviceHandler.device.Id,
1246 "intf-id": intfID,
1247 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001248
David K. Bainbridge794735f2020-02-11 21:01:37 -08001249 classifierProto, err := makeOpenOltClassifierField(classifier)
1250 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301251 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001252 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001253 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301254 log.Fields{
1255 "classifier": *classifierProto,
1256 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001257 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001258 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301259 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001260 }
1261
David K. Bainbridge794735f2020-02-11 21:01:37 -08001262 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001263 OnuId: int32(onuID),
1264 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001265 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001266 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001267 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001268 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001269 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001270 Classifier: classifierProto,
1271 Action: actionProto,
1272 Priority: int32(logicalFlow.Priority),
1273 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001274 PortNo: flowContext.portNo,
1275 TechProfileId: flowContext.tpID,
1276 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1277 PbitToGemport: flowContext.pbitToGem,
1278 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001279 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001280
David K. Bainbridge794735f2020-02-11 21:01:37 -08001281 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001282 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 -08001283 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001284
David K. Bainbridge794735f2020-02-11 21:01:37 -08001285 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001286}
1287
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001288// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001289func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1290 intfID := flowContext.intfID
1291 onuID := flowContext.onuID
1292 uniID := flowContext.uniID
1293 portNo := flowContext.portNo
1294 allocID := flowContext.allocID
1295 gemPortID := flowContext.gemPortID
1296 logicalFlow := flowContext.logicalFlow
1297 classifier := flowContext.classifier
1298 action := flowContext.action
1299
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001300 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301301 log.Fields{
1302 "intf-id": intfID,
1303 "onu-id": onuID,
1304 "port-no": portNo,
1305 "alloc-id": allocID,
1306 "gemport-id": gemPortID,
1307 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001308 "flow": logicalFlow,
1309 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301310
1311 uplinkClassifier := make(map[string]interface{})
1312 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301313
manikkaraj kbf256be2019-03-25 00:13:48 +05301314 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001315 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001316 uplinkClassifier[PacketTagType] = SingleTag
1317 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001318 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301319 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001320 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001321 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001322 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301323 "device-id": f.deviceHandler.device.Id,
1324 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001325 "intf-id": intfID,
1326 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001327 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301328 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001329 //Add Uplink EthType Flow
1330 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301331 log.Fields{
1332 "ul_classifier": uplinkClassifier,
1333 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001334 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301335 "device-id": f.deviceHandler.device.Id,
1336 "intf-id": intfID,
1337 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301338
David K. Bainbridge794735f2020-02-11 21:01:37 -08001339 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1340 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301341 return olterrors.NewErrInvalidValue(log.Fields{
1342 "classifier": uplinkClassifier,
1343 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301344 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001345 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301346 log.Fields{
1347 "classifier": *classifierProto,
1348 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001349 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001350 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301351 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301352 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001353 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301354 log.Fields{
1355 "action": *actionProto,
1356 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001357 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301358 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301359 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001360 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301361 "action": action,
1362 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001363 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301364 }
1365
David K. Bainbridge794735f2020-02-11 21:01:37 -08001366 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001367 OnuId: int32(onuID),
1368 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001369 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001370 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001371 AllocId: int32(allocID),
1372 NetworkIntfId: int32(networkIntfID),
1373 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301374 Classifier: classifierProto,
1375 Action: actionProto,
1376 Priority: int32(logicalFlow.Priority),
1377 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001378 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001379 TechProfileId: flowContext.tpID,
1380 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1381 PbitToGemport: flowContext.pbitToGem,
1382 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001383 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001384 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001385 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001386 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001387 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301388 log.Fields{
1389 "device-id": f.deviceHandler.device.Id,
1390 "onu-id": onuID,
1391 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001392 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301393 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001394
David K. Bainbridge794735f2020-02-11 21:01:37 -08001395 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301396}
1397
David K. Bainbridge794735f2020-02-11 21:01:37 -08001398func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001399 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001400
1401 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1402 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1403 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001404 if vlanID != ReservedVlan {
1405 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001406 classifier.OVid = vid
1407 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301408 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301409 // The classifierInfo[Metadata] carries the vlan that the OLT see when it receives packet from the ONU
David K. Bainbridge82efc492019-09-04 09:57:11 -07001410 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1411 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301412 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1413 // If OLT is using transparent tag mechanism, then it classifies whatever tag it sees to/from ONU which
1414 //is OVid from the perspective of the OLT. When OLT also places or pops the outer tag, then classifierInfo[Metadata]
1415 // becomes the IVid.
1416 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1417 if vid != ReservedVlan {
1418 classifier.IVid = vid
1419 }
1420 } else {
1421 if vid != ReservedVlan {
1422 classifier.OVid = vid
1423 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001424 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301425 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301426 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001427 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301428 classifier.OPbits = vlanPcp
1429 } else {
1430 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301431 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001432 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1433 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1434 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1435 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001436 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001437 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1438 classifier.PktTagType = pktTagType
1439
1440 switch pktTagType {
1441 case SingleTag:
1442 case DoubleTag:
1443 case Untagged:
1444 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001445 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301446 }
1447 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001448 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301449}
1450
Gamze Abaka724d0852020-03-18 12:10:24 +00001451func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001452 var actionCmd openoltpb2.ActionCmd
1453 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301454 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001455 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301456 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001457 if _, ok := actionInfo[VlanPcp]; ok {
1458 action.Cmd.RemarkInnerPbits = true
1459 action.IPbits = actionInfo[VlanPcp].(uint32)
1460 if _, ok := actionInfo[VlanVid]; ok {
1461 action.Cmd.TranslateInnerTag = true
1462 action.IVid = actionInfo[VlanVid].(uint32)
1463 }
1464 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001465 } else if _, ok := actionInfo[PushVlan]; ok {
1466 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301467 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001468 if _, ok := actionInfo[VlanPcp]; ok {
1469 action.OPbits = actionInfo[VlanPcp].(uint32)
1470 action.Cmd.RemarkOuterPbits = true
1471 if _, ok := classifierInfo[VlanVid]; ok {
1472 action.IVid = classifierInfo[VlanVid].(uint32)
1473 action.Cmd.TranslateInnerTag = true
1474 }
1475 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001476 } else if _, ok := actionInfo[TrapToHost]; ok {
1477 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301478 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301479 // When OLT is transparent to vlans no-action is valid.
1480 /*
1481 else {
1482 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1483 }
1484 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001485 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301486}
1487
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001488// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001489func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001490 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301491}
1492
Gamze Abakafee36392019-10-03 11:17:24 +00001493// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001494// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1495// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1496// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1497// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1498// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1499// because it was observed that if the ONU device was deleted too soon after the flows were
1500// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1501// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1502// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001503func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301504 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001505 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1506
Gamze Abakafee36392019-10-03 11:17:24 +00001507 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001508
1509 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001510 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001511 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1512 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
1513 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1514 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1515 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1516 log.Fields{
1517 "tp-id": tpID,
1518 "path": tpPath})
1519 }
1520 switch tpInstance := tpInst.(type) {
1521 case *tp_pb.TechProfileInstance:
1522 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1523 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1524 }
1525 // Force cleanup scheduler/queues -- end
1526
1527 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301528 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001529 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301530 // return err
1531 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001532 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001533 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 +00001534 }
1535 return nil
1536}
1537
1538// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301539func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001540 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001541 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001542 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001543 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301544 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1545 log.Fields{
1546 "tp-id": tpID,
1547 "uni-port-name": uniPortName,
1548 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001549 }
1550 return nil
1551}
1552
David K. Bainbridge794735f2020-02-11 21:01:37 -08001553func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001554
1555 var intfID uint32
1556 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1557 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1558 */
1559 if deviceFlow.AccessIntfId != -1 {
1560 intfID = uint32(deviceFlow.AccessIntfId)
1561 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001562 // We need to log the valid interface ID.
1563 // 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 +00001564 intfID = uint32(deviceFlow.NetworkIntfId)
1565 }
1566
Neha Sharma96b7bf22020-06-15 10:37:32 +00001567 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301568 "flow": *deviceFlow,
1569 "device-id": f.deviceHandler.device.Id,
1570 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001571 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001572
1573 st, _ := status.FromError(err)
1574 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001575 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001576 "err": err,
1577 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301578 "device-id": f.deviceHandler.device.Id,
1579 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001580 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301581 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001582
1583 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001584 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301585 log.Fields{"err": err,
1586 "device-flow": deviceFlow,
1587 "device-id": f.deviceHandler.device.Id,
1588 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001589 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001590 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001591 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301592 log.Fields{
1593 "flow": *deviceFlow,
1594 "device-id": f.deviceHandler.device.Id,
1595 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001596
1597 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1598 if deviceFlow.AccessIntfId != -1 {
1599 // No need to register the flow if it is a trap on nni flow.
1600 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1601 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1602 return err
1603 }
1604 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001605 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001606}
1607
Neha Sharma96b7bf22020-06-15 10:37:32 +00001608func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1609 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301610 log.Fields{
1611 "flow": *deviceFlow,
1612 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001613 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001614 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001615 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001616 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301617 log.Fields{
1618 "err": err,
1619 "deviceFlow": deviceFlow,
1620 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001621 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001622 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001623 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001624 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001625
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001626 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001627 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001628 "of-flow-id": ofFlowID,
1629 "flow": *deviceFlow,
1630 "device-id": f.deviceHandler.device.Id,
1631 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001632 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301633}
1634
David K. Bainbridge794735f2020-02-11 21:01:37 -08001635func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001636
1637 classifierInfo := make(map[string]interface{})
1638 actionInfo := make(map[string]interface{})
1639
1640 classifierInfo[EthType] = uint32(LldpEthType)
1641 classifierInfo[PacketTagType] = Untagged
1642 actionInfo[TrapToHost] = true
1643
1644 // LLDP flow is installed to trap LLDP packets on the NNI port.
1645 // We manage flow_id resource pool on per PON port basis.
1646 // Since this situation is tricky, as a hack, we pass the NNI port
1647 // index (network_intf_id) as PON port Index for the flow_id resource
1648 // pool. Also, there is no ONU Id available for trapping LLDP packets
1649 // on NNI port, use onu_id as -1 (invalid)
1650 // ****************** CAVEAT *******************
1651 // This logic works if the NNI Port Id falls within the same valid
1652 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1653 // we need to have a re-look at this.
1654 // *********************************************
1655
1656 var onuID = -1
1657 var uniID = -1
1658 var gemPortID = -1
1659
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001660 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001661 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301662 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001663 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001664 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001665 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001666 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001667 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001668
David K. Bainbridge794735f2020-02-11 21:01:37 -08001669 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1670 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301671 return olterrors.NewErrInvalidValue(
1672 log.Fields{
1673 "classifier": classifierInfo,
1674 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001675 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001676 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301677 log.Fields{
1678 "classifier": *classifierProto,
1679 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001680 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001681 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301682 return olterrors.NewErrInvalidValue(
1683 log.Fields{
1684 "action": actionInfo,
1685 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001686 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001687 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301688 log.Fields{
1689 "action": *actionProto,
1690 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001691
1692 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1693 OnuId: int32(onuID), // OnuId not required
1694 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001695 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001696 FlowType: Downstream,
1697 NetworkIntfId: int32(networkInterfaceID),
1698 GemportId: int32(gemPortID),
1699 Classifier: classifierProto,
1700 Action: actionProto,
1701 Priority: int32(flow.Priority),
1702 Cookie: flow.Cookie,
1703 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001704 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001705 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301706 log.Fields{
1707 "flow": downstreamflow,
1708 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001709 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001710 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301711 log.Fields{
1712 "device-id": f.deviceHandler.device.Id,
1713 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001714 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001715
David K. Bainbridge794735f2020-02-11 21:01:37 -08001716 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301717}
1718
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001719func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1720 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001721}
1722
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001723//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001724func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001725 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1726 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1727 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001728 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301729 log.Fields{
1730 "intf-id": intfID,
1731 "onu-id": onuID,
1732 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001733 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001734 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301735 return nil, olterrors.NewErrNotFound("onu-child-device",
1736 log.Fields{
1737 "onu-id": onuID,
1738 "intf-id": intfID,
1739 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001740 }
khenaidoo106c61a2021-08-11 18:05:46 -04001741 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001742 //better to ad the device to cache here.
1743 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1744 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001745 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301746 log.Fields{
1747 "intf-id": intfID,
1748 "onu-id": onuID,
1749 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001750 }
1751
1752 return onuDev.(*OnuDevice), nil
1753}
1754
1755//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001756func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1757 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301758 log.Fields{
1759 "pon-port": intfID,
1760 "onu-id": onuID,
1761 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001762 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001763 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001764 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301765 return nil, olterrors.NewErrNotFound("onu",
1766 log.Fields{
1767 "interface-id": parentPortNo,
1768 "onu-id": onuID,
1769 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001770 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301771 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001772 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301773 log.Fields{
1774 "device-id": f.deviceHandler.device.Id,
1775 "child_device_id": onuDevice.Id,
1776 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301777 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301778}
1779
Neha Sharma96b7bf22020-06-15 10:37:32 +00001780func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1781 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301782 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001783 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301784 log.Fields{
1785 "intf-id": intfID,
1786 "onu-id": onuID,
1787 "uni-id": uniID,
1788 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001789 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301790 }
1791
khenaidoodc2116e2021-10-19 17:33:19 -04001792 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001793 DeviceId: onuDev.deviceID,
1794 UniId: uniID,
1795 TpInstancePath: tpPath,
1796 GemPortId: gemPortID,
1797 }
1798 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1799
1800 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301801 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1802 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001803 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1804 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301805 "onu-id": onuDev.deviceID,
1806 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001807 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301808 }
khenaidoo106c61a2021-08-11 18:05:46 -04001809
Neha Sharma96b7bf22020-06-15 10:37:32 +00001810 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301811 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001812 "msg": delGemPortMsg,
1813 "from-adapter": f.deviceHandler.device.Type,
1814 "to-adapter": onuDev.deviceType,
1815 "device-id": f.deviceHandler.device.Id,
1816 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301817 return nil
1818}
1819
Neha Sharma96b7bf22020-06-15 10:37:32 +00001820func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1821 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301822 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001823 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301824 log.Fields{
1825 "intf-id": intfID,
1826 "onu-id": onuID,
1827 "uni-id": uniID,
1828 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001829 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301830 }
1831
khenaidoodc2116e2021-10-19 17:33:19 -04001832 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001833 DeviceId: onuDev.deviceID,
1834 UniId: uniID,
1835 TpInstancePath: tpPath,
1836 AllocId: allocID,
1837 }
1838
Neha Sharma96b7bf22020-06-15 10:37:32 +00001839 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301840 log.Fields{
1841 "msg": *delTcontMsg,
1842 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001843
1844 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301845 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1846 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001847 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1848 "to-adapter": onuDev.adapterEndpoint,
1849 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301850 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001851 "device-id": f.deviceHandler.device.Id}, err)
1852
Girish Gowdra6b130582019-11-20 16:45:20 +05301853 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001854 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301855 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001856 "msg": delTcontMsg,
1857 "device-id": f.deviceHandler.device.Id,
1858 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301859 return nil
1860}
1861
Girish Gowdrac3037402020-01-22 20:29:53 +05301862// Once the gemport is released for a given onu, it also has to be cleared from local cache
1863// which was used for deriving the gemport->logicalPortNo during packet-in.
1864// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1865// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001866func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001867 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301868 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001869 "gem-port-id": gemPortID,
1870 "intf-id": intfID,
1871 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001872 "device-id": f.deviceHandler.device.Id})
1873 f.onuGemInfoLock.RLock()
1874 onugem, ok := f.onuGemInfoMap[onuID]
1875 f.onuGemInfoLock.RUnlock()
1876 if !ok {
1877 logger.Warnw(ctx, "onu gem info already cleared from cache", log.Fields{
1878 "gem-port-id": gemPortID,
1879 "intf-id": intfID,
1880 "onu-id": onuID,
1881 "device-id": f.deviceHandler.device.Id})
1882 return
1883 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001884deleteLoop:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001885 for j, gem := range onugem.GemPorts {
1886 // If the gemport is found, delete it from local cache.
1887 if gem == gemPortID {
1888 onugem.GemPorts = append(onugem.GemPorts[:j], onugem.GemPorts[j+1:]...)
1889 f.onuGemInfoLock.Lock()
1890 f.onuGemInfoMap[onuID] = onugem
1891 f.onuGemInfoLock.Unlock()
1892 logger.Infow(ctx, "removed-gemport-from-local-cache",
1893 log.Fields{
1894 "intf-id": intfID,
1895 "onu-id": onuID,
1896 "deletedgemport-id": gemPortID,
1897 "gemports": onugem.GemPorts,
1898 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001899 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301900 }
1901 }
1902}
1903
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301904//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001905// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001906func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Gamze Abaka745ccb72021-11-18 11:29:58 +00001907 flowID uint64, portNum uint32, tpID uint32) error {
1908
1909 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001910
Girish Gowdraa482f272021-03-24 23:04:19 -07001911 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1912 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001913 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1914 log.Fields{
1915 "tpPath": tpPath,
1916 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001917
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001918 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001919 if err != nil || techprofileInst == nil {
1920 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1921 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1922 if childDevice == nil {
1923 // happens when subscriber un-provision is immediately followed by child device delete
1924 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1925 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1926 return nil
1927 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001928 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1929 log.Fields{
1930 "tp-id": tpID,
1931 "path": tpPath}, err)
1932 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001933
1934 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001935 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001936 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001937 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1938 gemPortID := gemPort.GemportId
1939 used := f.isGemPortUsedByAnotherFlow(gemPortID, flowID)
1940 if used {
1941 f.gemToFlowIDsKey.RLock()
1942 flowIDs := f.gemToFlowIDs[gemPortID]
1943 f.gemToFlowIDsKey.RUnlock()
1944
1945 for i, flowIDinMap := range flowIDs {
1946 if flowIDinMap == flowID {
1947 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1948 f.gemToFlowIDsKey.Lock()
1949 f.gemToFlowIDs[gemPortID] = flowIDs
1950 f.gemToFlowIDsKey.Unlock()
1951 // everytime gemToFlowIDs cache is updated the same should be updated
1952 // in kv store by calling UpdateFlowIDsForGem
1953 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, gemPortID, flowIDs); err != nil {
1954 return err
1955 }
1956 break
1957 }
1958 }
1959 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1960 log.Fields{
1961 "gemport-id": gemPortID,
1962 "usedByFlows": flowIDs,
1963 "currentFlow": flowID,
1964 "device-id": f.deviceHandler.device.Id})
1965 allGemPortsFree = false
1966 }
1967 }
1968 if !allGemPortsFree {
1969 return nil
1970 }
1971 }
1972
1973 logger.Debugw(ctx, "all-gem-ports-are-free-to-be-deleted", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
1974 switch techprofileInst := techprofileInst.(type) {
1975 case *tp_pb.TechProfileInstance:
1976 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
1977 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQueue)
1978 if !allocExists {
Girish Gowdraa482f272021-03-24 23:04:19 -07001979 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001980 logger.Warn(ctx, err)
1981 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001982 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001983 logger.Warn(ctx, err)
1984 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001985
1986 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
1987 if err := f.RemoveSchedulerQueues(ctx, schedQueue); err != nil {
1988 logger.Warn(ctx, err)
1989 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001990 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001991 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId)
1992
1993 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
1994 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
1995 if err := f.RemoveSchedulerQueues(ctx, schedQueue); err != nil {
1996 logger.Warn(ctx, err)
1997 }
1998 }
1999
2000 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2001 gemPortID := gemPort.GemportId
2002 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), gemPortID)
2003 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), gemPortID) // ignore error and proceed.
2004
2005 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gemPortID); err == nil {
2006 //everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
2007 // by calling DeleteFlowIDsForGem
2008 f.gemToFlowIDsKey.Lock()
2009 delete(f.gemToFlowIDs, gemPortID)
2010 f.gemToFlowIDsKey.Unlock()
2011 } else {
2012 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
2013 log.Fields{
2014 "err": err,
2015 "intf": intfID,
2016 "onu-id": onuID,
2017 "uni-id": uniID,
2018 "device-id": f.deviceHandler.device.Id,
2019 "gemport-id": gemPortID})
2020 }
2021
2022 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), gemPortID)
2023
2024 // Delete the gem port on the ONU.
2025 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPortID, tpPath); err != nil {
2026 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2027 log.Fields{
2028 "err": err,
2029 "intfID": intfID,
2030 "onu-id": onuID,
2031 "uni-id": uniID,
2032 "device-id": f.deviceHandler.device.Id,
2033 "gemport-id": gemPortID})
2034 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002035 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002036 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002037 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07002038 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002039 logger.Warn(ctx, err)
2040 }
Girish Gowdraa482f272021-03-24 23:04:19 -07002041 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002042 logger.Warn(ctx, err)
2043 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002044 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002045 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002046 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002047 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302048 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002049 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302050 "onu-id": onuID,
2051 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002052 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002053 "alloc-id": techprofileInst.AllocId,
2054 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002055 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002056 default:
2057 logger.Errorw(ctx, "error-unknown-tech",
2058 log.Fields{
2059 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002060 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302061 return nil
2062}
2063
David K. Bainbridge794735f2020-02-11 21:01:37 -08002064// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002065func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002066 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302067 log.Fields{
2068 "flowDirection": flowDirection,
2069 "flow": *flow,
2070 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002071
2072 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002073 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002074 }
2075
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302076 classifierInfo := make(map[string]interface{})
2077
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002078 portNum, Intf, onu, uni, inPort, ethType, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302079 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002080 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002081 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302082 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302083
David K. Bainbridge794735f2020-02-11 21:01:37 -08002084 onuID := int32(onu)
2085 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002086 tpID, err := getTpIDFromFlow(ctx, flow)
2087 if err != nil {
2088 return olterrors.NewErrNotFound("tp-id",
2089 log.Fields{
2090 "flow": flow,
2091 "intf-id": Intf,
2092 "onu-id": onuID,
2093 "uni-id": uniID,
2094 "device-id": f.deviceHandler.device.Id}, err)
2095 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302096
2097 for _, field := range flows.GetOfbFields(flow) {
2098 if field.Type == flows.IP_PROTO {
2099 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002100 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302101 }
2102 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002103 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302104 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002105 "flow-id": flow.Id,
2106 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302107 "onu-id": onuID,
2108 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302109
2110 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2111 onuID = -1
2112 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002113 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002114 Intf, err = plt.IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002115 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002116 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002117 log.Fields{
2118 "port-number": inPort,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002119 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002120 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002121 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302122 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002123
2124 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2125 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002126 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2127 return err
2128 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002129
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002130 // Delete the flow-id to gemport list entry from the map now the flow is deleted.
Gamze Abaka745ccb72021-11-18 11:29:58 +00002131 f.flowIDToGemsLock.Lock()
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002132 delete(f.flowIDToGems, flow.Id)
2133 f.flowIDToGemsLock.Unlock()
2134
Gamze Abaka745ccb72021-11-18 11:29:58 +00002135 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID); err != nil {
2136 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2137 "flow-id": flow.Id,
2138 "device-id": f.deviceHandler.device.Id,
2139 "onu-id": onuID,
2140 "intf": Intf,
2141 "err": err,
2142 })
2143 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302144 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002145
Girish Gowdra82c80982021-03-26 16:22:02 -07002146 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2147 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2148 return err
2149 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002150 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002151}
2152
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002153//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002154func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002155
Matteo Scandolof16389e2021-05-18 00:47:08 +00002156 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302157 var direction string
2158 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002159
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302160 for _, action := range flows.GetActions(flow) {
2161 if action.Type == flows.OUTPUT {
2162 if out := action.GetOutput(); out != nil {
2163 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002164 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302165 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002166 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002167 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002168 }
2169 }
2170 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002171
2172 if flows.HasGroup(flow) {
2173 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002174 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002175 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302176 direction = Upstream
2177 } else {
2178 direction = Downstream
2179 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302180
Girish Gowdracefae192020-03-19 18:14:10 -07002181 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002182 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002183
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002184 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002185}
2186
Esin Karamanae41e2b2019-12-17 18:13:13 +00002187//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2188func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002189 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002190 if ethType, ok := classifierInfo[EthType]; ok {
2191 if ethType.(uint32) == IPv4EthType {
2192 if ipProto, ok := classifierInfo[IPProto]; ok {
2193 if ipProto.(uint32) == IgmpProto {
2194 return true
2195 }
2196 }
2197 }
2198 }
2199 }
2200 return false
2201}
2202
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002203// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002204func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002205 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2206 // The device itself is going to be reset as part of deletion. So nothing to be done.
2207 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2208 return nil
2209 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002210 // Step1 : Fill flowControlBlock
2211 // Step2 : Push the flowControlBlock to ONU channel
2212 // Step3 : Wait on response channel for response
2213 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002214 startTime := time.Now()
2215 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002216 errChan := make(chan error)
2217 flowCb := flowControlBlock{
2218 ctx: ctx,
2219 addFlow: addFlow,
2220 flow: flow,
2221 flowMetadata: flowMetadata,
2222 errChan: &errChan,
2223 }
2224 inPort, outPort := getPorts(flow)
2225 var onuID uint32
2226 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002227 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002228 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002229 if f.flowHandlerRoutineActive[onuID] {
2230 // inPort or outPort is InvalidPort for trap-from-nni flows.
2231 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2232 // Send the flowCb on the ONU flow channel
2233 f.incomingFlows[onuID] <- flowCb
2234 // Wait on the channel for flow handlers return value
2235 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002236 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002237 return err
2238 }
2239 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2240 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002241}
2242
2243// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2244// 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 -07002245func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002246 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002247 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002248 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002249 // block on the channel to receive an incoming flow
2250 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002251 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002252 if flowCb.addFlow {
2253 logger.Info(flowCb.ctx, "adding-flow-start")
2254 startTime := time.Now()
2255 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2256 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2257 // Pass the return value over the return channel
2258 *flowCb.errChan <- err
2259 } else {
2260 logger.Info(flowCb.ctx, "removing-flow-start")
2261 startTime := time.Now()
2262 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2263 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2264 // Pass the return value over the return channel
2265 *flowCb.errChan <- err
2266 }
2267 case <-stopHandler:
2268 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2269 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002270 }
2271 }
2272}
2273
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002274// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002275func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002276 for i, v := range f.stopFlowHandlerRoutine {
2277 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002278 select {
2279 case v <- true:
2280 case <-time.After(time.Second * 5):
2281 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2282 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002283 }
2284 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002285 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002286 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2287}
2288
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002289// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302290// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002291func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002292 classifierInfo := make(map[string]interface{})
2293 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002294 var UsMeterID uint32
2295 var DsMeterID uint32
2296
Neha Sharma96b7bf22020-06-15 10:37:32 +00002297 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302298 log.Fields{
2299 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002300 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002301 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002302
Neha Sharma96b7bf22020-06-15 10:37:32 +00002303 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002304 if err != nil {
2305 // Error logging is already done in the called function
2306 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002307 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302308 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002309
Esin Karamanccb714b2019-11-29 15:02:06 +00002310 if flows.HasGroup(flow) {
2311 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002312 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002313 }
2314
manikkaraj k17652a72019-05-06 09:06:36 -04002315 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002316 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002317 if err != nil {
2318 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002319 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002320 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002321
Neha Sharma96b7bf22020-06-15 10:37:32 +00002322 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302323 log.Fields{
2324 "classifierinfo_inport": classifierInfo[InPort],
2325 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002326 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002327
Humera Kouser94d7a842019-08-25 19:04:32 -04002328 if ethType, ok := classifierInfo[EthType]; ok {
2329 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002330 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002331 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002332 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002333 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002334 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002335 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2336 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2337 }
2338 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002339 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002340 if ipProto, ok := classifierInfo[IPProto]; ok {
2341 if ipProto.(uint32) == IPProtoDhcp {
2342 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302343 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002344 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002345 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002346 }
2347 }
2348 }
2349 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002350 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002351 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002352 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002353 }
A R Karthick1f85b802019-10-11 05:06:05 +00002354
npujarec5762e2020-01-01 14:08:48 +05302355 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002356 // also update flowmgr cache
2357 f.onuGemInfoLock.Lock()
2358 onugem, ok := f.onuGemInfoMap[onuID]
2359 if ok {
2360 found := false
2361 for _, uni := range onugem.UniPorts {
2362 if uni == portNo {
2363 found = true
2364 break
2365 }
2366 }
2367 if !found {
2368 onugem.UniPorts = append(onugem.UniPorts, portNo)
2369 f.onuGemInfoMap[onuID] = onugem
2370 logger.Infow(ctx, "added uni port to onugem cache", log.Fields{"uni": portNo})
2371 }
2372 }
2373 f.onuGemInfoLock.Unlock()
A R Karthick1f85b802019-10-11 05:06:05 +00002374
Neha Sharma96b7bf22020-06-15 10:37:32 +00002375 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002376 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302377 return olterrors.NewErrNotFound("tpid-for-flow",
2378 log.Fields{
2379 "flow": flow,
2380 "intf-id": IntfID,
2381 "onu-id": onuID,
2382 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002383 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002384 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302385 log.Fields{
2386 "tp-id": TpID,
2387 "intf-id": intfID,
2388 "onu-id": onuID,
2389 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002390 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002391 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002392 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002393 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002394 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002395 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002396
2397 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002398 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002399}
Girish Gowdra3d633032019-12-10 16:37:05 +05302400
Esin Karamanccb714b2019-11-29 15:02:06 +00002401// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002402func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302403 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002404 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302405 "classifier-info": classifierInfo,
2406 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002407
Esin Karaman65409d82020-03-18 10:58:18 +00002408 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002409 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002410 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002411 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002412
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002413 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002414
David K. Bainbridge794735f2020-02-11 21:01:37 -08002415 onuID := NoneOnuID
2416 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002417
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002418 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002419 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002420 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002421 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002422 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2423 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002424 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002425 }
2426 groupID := actionInfo[GroupID].(uint32)
2427 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002428 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002429 FlowType: Multicast,
2430 NetworkIntfId: int32(networkInterfaceID),
2431 GroupId: groupID,
2432 Classifier: classifierProto,
2433 Priority: int32(flow.Priority),
2434 Cookie: flow.Cookie}
2435
Kent Hagermane6ff1012020-07-14 15:07:53 -04002436 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002437 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002438 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002439 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002440 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002441 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002442 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002443 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002444 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002445 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002446 //cached group can be removed now
2447 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002448 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002449 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002450 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002451
David K. Bainbridge794735f2020-02-11 21:01:37 -08002452 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002453}
2454
Esin Karaman65409d82020-03-18 10:58:18 +00002455//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2456func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2457 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002458 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002459 if err != nil {
2460 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2461 }
2462 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002463 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002464
2465 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2466 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002467}
2468
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002469//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002470func (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 -07002471
Neha Sharma96b7bf22020-06-15 10:37:32 +00002472 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302473 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002474 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302475 log.Fields{
2476 "intf-id": intfID,
2477 "onu-id": onuID,
2478 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002479 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302480 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002481 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002482
Neha Sharma96b7bf22020-06-15 10:37:32 +00002483 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002484 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002485 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002486 UniId: uniID,
2487 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002488 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002489 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002490 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002491
2492 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2493 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302494 return olterrors.NewErrCommunication("send-techprofile-download-request",
2495 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002496 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302497 "to-adapter": onuDev.deviceType,
2498 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002499 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002500 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002501 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302502 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302503}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002504
Girish Gowdra197acc12021-08-16 10:59:45 -07002505//AddOnuInfoToFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2506func (f *OpenOltFlowMgr) AddOnuInfoToFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302507
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002508 f.onuGemInfoLock.RLock()
2509 _, ok := f.onuGemInfoMap[onuID]
2510 f.onuGemInfoLock.RUnlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002511 // If the ONU already exists in onuGemInfo list, nothing to do
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002512 if ok {
2513 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2514 log.Fields{"onuID": onuID,
2515 "serialNum": serialNum})
2516 return nil
Girish Gowdra9602eb42020-09-09 15:50:39 -07002517 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002518
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002519 onuGemInfo := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2520 f.onuGemInfoLock.Lock()
2521 f.onuGemInfoMap[onuID] = &onuGemInfo
2522 f.onuGemInfoLock.Unlock()
2523 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onuID, onuGemInfo); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002524 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302525 }
Girish Gowdra197acc12021-08-16 10:59:45 -07002526 logger.Infow(ctx, "added-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302527 log.Fields{
2528 "intf-id": intfID,
2529 "onu-id": onuID,
2530 "serial-num": serialNum,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002531 "onu": onuGemInfo,
Shrey Baid26912972020-04-16 21:02:31 +05302532 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002533 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002534}
2535
Girish Gowdra197acc12021-08-16 10:59:45 -07002536//RemoveOnuInfoFromFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2537func (f *OpenOltFlowMgr) RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32) error {
2538
2539 f.onuGemInfoLock.Lock()
2540 delete(f.onuGemInfoMap, onuID)
2541 f.onuGemInfoLock.Unlock()
2542
2543 if err := f.resourceMgr.DelOnuGemInfo(ctx, intfID, onuID); err != nil {
2544 return err
2545 }
2546 logger.Infow(ctx, "deleted-onuinfo",
2547 log.Fields{
2548 "intf-id": intfID,
2549 "onu-id": onuID,
2550 "device-id": f.deviceHandler.device.Id})
2551 return nil
2552}
2553
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302554//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302555func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002556
Neha Sharma96b7bf22020-06-15 10:37:32 +00002557 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302558 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002559 "gem-port-id": gemPort,
2560 "intf-id": intfID,
2561 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002562 "device-id": f.deviceHandler.device.Id})
2563 f.onuGemInfoLock.RLock()
2564 onugem, ok := f.onuGemInfoMap[onuID]
2565 f.onuGemInfoLock.RUnlock()
2566 if !ok {
2567 logger.Warnw(ctx, "onu gem info is missing", log.Fields{
2568 "gem-port-id": gemPort,
2569 "intf-id": intfID,
2570 "onu-id": onuID,
2571 "device-id": f.deviceHandler.device.Id})
2572 return
2573 }
2574
2575 if onugem.OnuID == onuID {
2576 // check if gem already exists , else update the cache and kvstore
2577 for _, gem := range onugem.GemPorts {
2578 if gem == gemPort {
2579 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2580 log.Fields{
2581 "gem": gemPort,
2582 "device-id": f.deviceHandler.device.Id})
2583 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302584 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302585 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002586 onugem.GemPorts = append(onugem.GemPorts, gemPort)
2587 f.onuGemInfoLock.Lock()
2588 f.onuGemInfoMap[onuID] = onugem
2589 f.onuGemInfoLock.Unlock()
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002590 logger.Debugw(ctx, "updated onu gem info from cache", log.Fields{"onugem": onugem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002591 } else {
2592 logger.Warnw(ctx, "mismatched onu id", log.Fields{
2593 "gem-port-id": gemPort,
2594 "intf-id": intfID,
2595 "onu-id": onuID,
2596 "device-id": f.deviceHandler.device.Id})
2597 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302598 }
npujarec5762e2020-01-01 14:08:48 +05302599 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302600 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002601 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302602 log.Fields{
2603 "intf-id": intfID,
2604 "onu-id": onuID,
2605 "gemPort": gemPort,
2606 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002607 return
2608 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002609 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302610 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002611 "gem-port-id": gemPort,
2612 "intf-id": intfID,
2613 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002614 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002615}
2616
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002617//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302618func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002619 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002620
2621 if packetIn.IntfType == "pon" {
2622 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002623 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002624 onuID, uniID := packetIn.OnuId, packetIn.UniId
2625 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 +00002626
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002627 if packetIn.PortNo != 0 {
2628 logicalPortNum = packetIn.PortNo
2629 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002630 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002631 }
2632 // 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 +00002633 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002634 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002635 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002636 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002637
2638 if logger.V(log.DebugLevel) {
2639 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2640 log.Fields{
2641 "logical-port-num": logicalPortNum,
2642 "intf-type": packetIn.IntfType,
2643 "packet": hex.EncodeToString(packetIn.Pkt),
2644 })
2645 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002646 return logicalPortNum, nil
2647}
2648
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002649//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002650func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002651 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002652
2653 ctag, priority, err := getCTagFromPacket(ctx, packet)
2654 if err != nil {
2655 return 0, err
2656 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302657
Esin Karaman7fb80c22020-07-16 14:23:33 +00002658 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002659 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002660 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002661 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002662 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302663 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002664 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302665 log.Fields{
2666 "pktinkey": pktInkey,
2667 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002668
2669 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002670 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302671 //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 +00002672 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302673 if err == nil {
2674 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002675 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302676 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002677 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002678 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302679 log.Fields{
2680 "pktinkey": pktInkey,
2681 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302682 return gemPortID, nil
2683 }
2684 }
Shrey Baid26912972020-04-16 21:02:31 +05302685 return uint32(0), olterrors.NewErrNotFound("gem-port",
2686 log.Fields{
2687 "pktinkey": pktInkey,
2688 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002689
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002690}
2691
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002692func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2693 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002694 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002695 classifier[PacketTagType] = DoubleTag
2696 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002697 /* We manage flowId resource pool on per PON port basis.
2698 Since this situation is tricky, as a hack, we pass the NNI port
2699 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002700 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002701 on NNI port, use onu_id as -1 (invalid)
2702 ****************** CAVEAT *******************
2703 This logic works if the NNI Port Id falls within the same valid
2704 range of PON Port Ids. If this doesn't work for some OLT Vendor
2705 we need to have a re-look at this.
2706 *********************************************
2707 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002708 onuID := -1
2709 uniID := -1
2710 gemPortID := -1
2711 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002712 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302713 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302714 return olterrors.NewErrNotFound("nni-intreface-id",
2715 log.Fields{
2716 "classifier": classifier,
2717 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002718 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302719 }
2720
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002721 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002722 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002723 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002724 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002725
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002726 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2727 log.Fields{
2728 "classifier": classifier,
2729 "action": action,
2730 "flowId": logicalFlow.Id,
2731 "intf-id": networkInterfaceID})
2732
David K. Bainbridge794735f2020-02-11 21:01:37 -08002733 classifierProto, err := makeOpenOltClassifierField(classifier)
2734 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002735 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002736 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002737 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002738 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002739 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002740 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002741 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002742 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002743 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2744 OnuId: int32(onuID), // OnuId not required
2745 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002746 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002747 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002748 AllocId: int32(allocID), // AllocId not used
2749 NetworkIntfId: int32(networkInterfaceID),
2750 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002751 Classifier: classifierProto,
2752 Action: actionProto,
2753 Priority: int32(logicalFlow.Priority),
2754 Cookie: logicalFlow.Cookie,
2755 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002756 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002757 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002758 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002759 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002760 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002761}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002762
Esin Karamanae41e2b2019-12-17 18:13:13 +00002763//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2764func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2765 var packetType string
2766 ovid, ivid := false, false
2767 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2768 vid := vlanID & VlanvIDMask
2769 if vid != ReservedVlan {
2770 ovid = true
2771 }
2772 }
2773 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2774 vid := uint32(metadata)
2775 if vid != ReservedVlan {
2776 ivid = true
2777 }
2778 }
2779 if ovid && ivid {
2780 packetType = DoubleTag
2781 } else if !ovid && !ivid {
2782 packetType = Untagged
2783 } else {
2784 packetType = SingleTag
2785 }
2786 return packetType
2787}
2788
2789//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002790func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002791 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002792 action := make(map[string]interface{})
2793 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2794 action[TrapToHost] = true
2795 /* We manage flowId resource pool on per PON port basis.
2796 Since this situation is tricky, as a hack, we pass the NNI port
2797 index (network_intf_id) as PON port Index for the flowId resource
2798 pool. Also, there is no ONU Id available for trapping packets
2799 on NNI port, use onu_id as -1 (invalid)
2800 ****************** CAVEAT *******************
2801 This logic works if the NNI Port Id falls within the same valid
2802 range of PON Port Ids. If this doesn't work for some OLT Vendor
2803 we need to have a re-look at this.
2804 *********************************************
2805 */
2806 onuID := -1
2807 uniID := -1
2808 gemPortID := -1
2809 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002810 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002811 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302812 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002813 "classifier": classifier,
2814 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002815 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002816 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002817 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002818 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002819 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002820 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002821
David K. Bainbridge794735f2020-02-11 21:01:37 -08002822 classifierProto, err := makeOpenOltClassifierField(classifier)
2823 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002824 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002825 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002826 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002827 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002828 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002829 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002830 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002831 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002832 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2833 OnuId: int32(onuID), // OnuId not required
2834 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002835 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002836 FlowType: Downstream,
2837 AllocId: int32(allocID), // AllocId not used
2838 NetworkIntfId: int32(networkInterfaceID),
2839 GemportId: int32(gemPortID), // GemportId not used
2840 Classifier: classifierProto,
2841 Action: actionProto,
2842 Priority: int32(logicalFlow.Priority),
2843 Cookie: logicalFlow.Cookie,
2844 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002845 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002846 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002847 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002848 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002849
David K. Bainbridge794735f2020-02-11 21:01:37 -08002850 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002851}
2852
salmansiddiqui7ac62132019-08-22 03:58:50 +00002853func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2854 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302855 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002856 }
2857 if Dir == tp_pb.Direction_UPSTREAM {
2858 return "upstream", nil
2859 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2860 return "downstream", nil
2861 }
2862 return "", nil
2863}
2864
Kent Hagermane6ff1012020-07-14 15:07:53 -04002865// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302866func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002867 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002868 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002869 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002870 intfID := args[IntfID]
2871 onuID := args[OnuID]
2872 uniID := args[UniID]
2873 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002874 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002875 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002876 gemToAes := make(map[uint32]bool)
2877
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002878 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002879 var direction = tp_pb.Direction_UPSTREAM
2880 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002881 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002882 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002883 attributes = TpInst.UpstreamGemPortAttributeList
2884 } else {
2885 attributes = TpInst.DownstreamGemPortAttributeList
2886 direction = tp_pb.Direction_DOWNSTREAM
2887 }
2888 default:
2889 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002890 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002891 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002892
2893 if len(gemPorts) == 1 {
2894 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002895 gemPortID = gemPorts[0]
2896 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002897 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2898 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002899 pBitMap := attributes[idx].PbitMap
2900 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2901 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2902 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002903 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002904 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2905 if pbitSet == pbit1 {
2906 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2907 pbitToGem[pcp] = gemID
2908 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002909 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002910 }
2911 }
2912 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002913 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2914 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2915 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002916 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002917 }
2918
Gamze Abaka7650be62021-02-26 10:50:36 +00002919 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2920 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2921
salmansiddiqui7ac62132019-08-22 03:58:50 +00002922 if ipProto, ok := classifierInfo[IPProto]; ok {
2923 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002924 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002925 "tp-id": tpID,
2926 "alloc-id": allocID,
2927 "intf-id": intfID,
2928 "onu-id": onuID,
2929 "uni-id": uniID,
2930 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002931 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002932 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002933 logger.Warn(ctx, err)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002934 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002935 }
2936
Girish Gowdra32625212020-04-29 11:26:35 -07002937 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002938 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302939 log.Fields{
2940 "intf-id": intfID,
2941 "onu-id": onuID,
2942 "uni-id": uniID,
2943 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002944 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002945 logger.Warn(ctx, err)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002946 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002947 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002948 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002949 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002950 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002951 }
2952 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002953 if ethType.(uint32) == EapEthType {
2954 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002955 "intf-id": intfID,
2956 "onu-id": onuID,
2957 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002958 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002959 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002960 var vlanID uint32
2961 if val, ok := classifierInfo[VlanVid]; ok {
2962 vlanID = (val.(uint32)) & VlanvIDMask
2963 } else {
2964 vlanID = DefaultMgmtVlan
2965 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002966 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002967 logger.Warn(ctx, err)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002968 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002969 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002970 } else if ethType.(uint32) == PPPoEDEthType {
2971 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2972 "tp-id": tpID,
2973 "alloc-id": allocID,
2974 "intf-id": intfID,
2975 "onu-id": onuID,
2976 "uni-id": uniID,
2977 })
2978 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002979 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002980 logger.Warn(ctx, err)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002981 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002982 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002983 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002984 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002985 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002986 "intf-id": intfID,
2987 "onu-id": onuID,
2988 "uni-id": uniID,
2989 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002990 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002991 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002992 logger.Warn(ctx, err)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002993 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002994 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002995 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002996 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002997 "intf-id": intfID,
2998 "onu-id": onuID,
2999 "uni-id": uniID,
3000 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003001 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00003002 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003003 logger.Warn(ctx, err)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003004 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00003005 }
3006 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003007 return olterrors.NewErrInvalidValue(log.Fields{
3008 "intf-id": intfID,
3009 "onu-id": onuID,
3010 "uni-id": uniID,
3011 "classifier": classifierInfo,
3012 "action": actionInfo,
3013 "flow": flow},
3014 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003015 }
3016 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04003017 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003018 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003019 logger.Warn(ctx, err)
3020 }
3021 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003022 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00003023}
3024
Gamze Abaka745ccb72021-11-18 11:29:58 +00003025func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32, flowID uint64) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003026 f.gemToFlowIDsKey.RLock()
3027 flowIDList := f.gemToFlowIDs[gemPortID]
3028 f.gemToFlowIDsKey.RUnlock()
Gamze Abaka745ccb72021-11-18 11:29:58 +00003029 if len(flowIDList) > 0 {
3030 for _, id := range flowIDList {
3031 if flowID != id {
3032 return true
Gamze Abakafee36392019-10-03 11:17:24 +00003033 }
3034 }
3035 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00003036 return false
Gamze Abakacb0e6772021-06-10 08:32:12 +00003037}
Girish Gowdra54934262019-11-13 14:19:55 +05303038
Gamze Abakacb0e6772021-06-10 08:32:12 +00003039func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003040 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
3041 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
3042 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 +00003043 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303044 for i := 0; i < len(tpInstances); i++ {
3045 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00003046 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003047 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Gamze Abakacb0e6772021-06-10 08:32:12 +00003048 logger.Debugw(ctx, "alloc-is-in-use",
3049 log.Fields{
3050 "device-id": f.deviceHandler.device.Id,
3051 "intfID": sq.intfID,
3052 "onuID": sq.onuID,
3053 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003054 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00003055 })
3056 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303057 }
3058 }
3059 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003060 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003061}
3062
Neha Sharma96b7bf22020-06-15 10:37:32 +00003063func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003064 for _, field := range flows.GetOfbFields(flow) {
3065 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003066 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003068 } else if field.Type == flows.ETH_DST {
3069 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003070 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003071 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003072 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003073 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003074 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003075 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003076 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003077 } else if field.Type == flows.VLAN_VID {
Andrea Campanellafaa42152021-10-28 11:50:56 +05303078 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3079 if field.GetVlanVid() != ReservedVlan {
3080 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3081 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3082 }
Scott Baker355d1742019-10-24 10:57:52 -07003083 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003084 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003085 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003086 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003087 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003088 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003089 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003090 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003091 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003092 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003093 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003094 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003095 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003096 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003097 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003098 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003099 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003100 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003101 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003102 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003103 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003104 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003105 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003106 return
3107 }
3108 }
3109}
3110
Neha Sharma96b7bf22020-06-15 10:37:32 +00003111func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003112 for _, action := range flows.GetActions(flow) {
3113 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003114 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003115 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003116 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003117 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003118 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003119 }
Scott Baker355d1742019-10-24 10:57:52 -07003120 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003121 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003122 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003123 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003124 if out := action.GetPush(); out != nil {
3125 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003126 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003127 } else {
3128 actionInfo[PushVlan] = true
3129 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003130 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303131 log.Fields{
3132 "push-tpid": actionInfo[TPID].(uint32),
3133 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003134 }
3135 }
Scott Baker355d1742019-10-24 10:57:52 -07003136 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003137 if out := action.GetSetField(); out != nil {
3138 if field := out.GetField(); field != nil {
3139 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003140 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003141 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003142 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3143 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003144 }
3145 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003146 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003147 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003148 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003149 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003150 }
3151 }
3152 return nil
3153}
3154
Neha Sharma96b7bf22020-06-15 10:37:32 +00003155func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003156 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003157 fieldtype := ofbField.GetType()
3158 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003159 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3160 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003161 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003162 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003163 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003164 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003165 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3166 pcp := ofbField.GetVlanPcp()
3167 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003168 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003169 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003170 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003171 }
3172 }
3173}
3174
Neha Sharma96b7bf22020-06-15 10:37:32 +00003175func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003176 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003177 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003178 } else {
3179 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003180 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003181 }
3182}
3183
Neha Sharma96b7bf22020-06-15 10:37:32 +00003184func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003185 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003186 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003187 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003188 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003189 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003190 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003191 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303192 log.Fields{
3193 "newinport": classifierInfo[InPort].(uint32),
3194 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003195 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303196 return olterrors.NewErrNotFound("child-in-port",
3197 log.Fields{
3198 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3199 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003200 }
3201 }
3202 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003203 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003204 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003205 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003206 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003207 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003208 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303209 log.Fields{
3210 "newoutport": actionInfo[Output].(uint32),
3211 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003212 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303213 return olterrors.NewErrNotFound("out-port",
3214 log.Fields{
3215 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3216 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003217 }
3218 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003219 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003220 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003221 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003222 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303223 log.Fields{
3224 "newinport": actionInfo[Output].(uint32),
3225 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003226 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303227 return olterrors.NewErrNotFound("nni-port",
3228 log.Fields{
3229 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3230 "in-port": classifierInfo[InPort].(uint32),
3231 "out-port": actionInfo[Output].(uint32),
3232 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003233 }
3234 }
3235 }
3236 return nil
3237}
Gamze Abakafee36392019-10-03 11:17:24 +00003238
Neha Sharma96b7bf22020-06-15 10:37:32 +00003239func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003240 /* Metadata 8 bytes:
3241 Most Significant 2 Bytes = Inner VLAN
3242 Next 2 Bytes = Tech Profile ID(TPID)
3243 Least Significant 4 Bytes = Port ID
3244 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3245 subscriber related flows.
3246 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003247 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003248 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003249 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003250 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003251 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003252 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003253}
3254
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003255func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3256 for _, sliceElement := range slice {
3257 if sliceElement == item {
3258 return slice
3259 }
3260 }
3261 return append(slice, item)
3262}
3263
3264func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003265 for _, sliceElement := range slice {
3266 if sliceElement == item {
3267 return slice
3268 }
3269 }
3270 return append(slice, item)
3271}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303272
3273// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003274func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303275
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003276 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303277 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003278 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003279 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003280 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003281 log.Fields{
3282 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003283 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003284 return uint32(0), err
3285 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003286 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303287 return intfID, nil
3288 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003289 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003290 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003291 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003292 log.Fields{
3293 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003294 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003295 return uint32(0), err
3296 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003297 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303298 return intfID, nil
3299 }
3300 return uint32(0), nil
3301}
3302
3303// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003304func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3305 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3306 if err != nil {
3307 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3308 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3309 return
3310 }
3311 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003312
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003313 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003314 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003315 f.packetInGemPortLock.RUnlock()
3316
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303317 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003318 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003319 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 +05303320 log.Fields{
3321 "pktinkey": pktInkey,
3322 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003323 return
3324 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303325 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003326 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003327 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003328 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003329
npujarec5762e2020-01-01 14:08:48 +05303330 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003331 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 +05303332 log.Fields{
3333 "pktinkey": pktInkey,
3334 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303335}
3336
Esin Karaman7fb80c22020-07-16 14:23:33 +00003337//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3338func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3339 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003340 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003341 return 0, 0, errors.New("invalid packet length")
3342 }
3343 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3344 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3345
3346 var index int8
3347 if outerEthType == 0x8100 {
3348 if innerEthType == 0x8100 {
3349 // q-in-q 802.1ad or 802.1q double tagged packet.
3350 // get the inner vlanId
3351 index = 18
3352 } else {
3353 index = 14
3354 }
3355 priority := (packet[index] >> 5) & 0x7
3356 //13 bits composes vlanId value
3357 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3358 return vlan, priority, nil
3359 }
3360 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3361 return 0, 0, nil
3362}
3363
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003364func (f *OpenOltFlowMgr) loadFlowIDsForGemAndGemIDsForFlow(ctx context.Context) {
3365 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - start")
3366 f.onuGemInfoLock.RLock()
3367 f.gemToFlowIDsKey.Lock()
3368 f.flowIDToGemsLock.Lock()
3369 for _, og := range f.onuGemInfoMap {
3370 for _, gem := range og.GemPorts {
3371 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, f.ponPortIdx, gem)
Gamze Abaka6f345c12021-09-08 01:14:33 +00003372 if err == nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003373 f.gemToFlowIDs[gem] = flowIDs
3374 for _, flowID := range flowIDs {
3375 if _, ok := f.flowIDToGems[flowID]; !ok {
3376 f.flowIDToGems[flowID] = []uint32{gem}
3377 } else {
3378 f.flowIDToGems[flowID] = appendUnique32bit(f.flowIDToGems[flowID], gem)
3379 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303380 }
3381 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303382 }
3383 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003384 f.flowIDToGemsLock.Unlock()
3385 f.gemToFlowIDsKey.Unlock()
3386 f.onuGemInfoLock.RUnlock()
3387 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - end")
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303388}
Esin Karamanccb714b2019-11-29 15:02:06 +00003389
Girish Gowdra9602eb42020-09-09 15:50:39 -07003390//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3391// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003392func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003393 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003394 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3395 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003396 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003397 "flow-id": flow.Id,
3398 "device-id": f.deviceHandler.device.Id})
3399 // Remove from device
3400 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3401 // DKB
3402 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3403 log.Fields{
3404 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003405 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003406 return err
3407 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003408
3409 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003410}
3411
khenaidoodc2116e2021-10-19 17:33:19 -04003412func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003413 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003414 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003415 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003416 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003417 }
3418
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003419 switch tpInst := tpInst.(type) {
3420 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003421 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003422 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003423 DeviceId: onuDeviceID,
3424 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003425 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003426 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003427 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003428 case *tp_pb.EponTechProfileInstance:
3429 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003430 DeviceId: onuDeviceID,
3431 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003432 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003433 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003434 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003435 default:
3436 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003437 }
khenaidoodc2116e2021-10-19 17:33:19 -04003438 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003439 DeviceId: onuDeviceID,
3440 UniId: uniID,
3441 TpInstancePath: tpPath,
3442 TechTpInstance: nil,
3443 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003444}
3445
Girish Gowdrabcf98af2021-07-01 08:24:42 -07003446func (f *OpenOltFlowMgr) getOnuGemInfoList(ctx context.Context) []rsrcMgr.OnuGemInfo {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003447 var onuGemInfoLst []rsrcMgr.OnuGemInfo
3448 f.onuGemInfoLock.RLock()
3449 defer f.onuGemInfoLock.RUnlock()
3450 for _, v := range f.onuGemInfoMap {
3451 onuGemInfoLst = append(onuGemInfoLst, *v)
3452 }
3453 return onuGemInfoLst
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003454}