blob: 57833fa7064aeea1dc30fc67be713de6190864bc [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 Gowdra4736e5c2021-08-25 15:19:10 -0700253 flowMgr.stopFlowHandlerRoutine[i] = make(chan bool, 1)
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 */
387 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
388
Andrea Campanellabfe08432020-09-11 17:07:03 +0200389 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530390}
391
salmansiddiqui7ac62132019-08-22 03:58:50 +0000392// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530393func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400394
Neha Sharma96b7bf22020-06-15 10:37:32 +0000395 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530396 log.Fields{"dir": sq.direction,
397 "intf-id": sq.intfID,
398 "onu-id": sq.onuID,
399 "uni-id": sq.uniID,
400 "tp-id": sq.tpID,
401 "meter-id": sq.meterID,
402 "tp-inst": sq.tpInst,
403 "flowmetadata": sq.flowMetadata,
404 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400405
Gamze Abakafee36392019-10-03 11:17:24 +0000406 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000407 if err != nil {
408 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400409 }
410
411 /* Lets make a simple assumption that if the meter-id is present on the KV store,
412 * then the scheduler and queues configuration is applied on the OLT device
413 * in the given direction.
414 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000415
Manikkaraj kb1d51442019-07-23 10:41:02 -0400416 var SchedCfg *tp_pb.SchedulerConfig
Girish Gowdraa482f272021-03-24 23:04:19 -0700417 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400418 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530419 return olterrors.NewErrNotFound("meter",
420 log.Fields{"intf-id": sq.intfID,
421 "onu-id": sq.onuID,
422 "uni-id": sq.uniID,
423 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400424 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000425
Girish Gowdraa482f272021-03-24 23:04:19 -0700426 if meterInfo != nil {
427 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id, "meter-id": sq.meterID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700428 if meterInfo.MeterID == sq.meterID {
Girish Gowdraa482f272021-03-24 23:04:19 -0700429 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
430 return err
431 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400433 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530434 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800435 "unsupported": "meter-id",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700436 "kv-store-meter-id": meterInfo.MeterID,
Shrey Baid26912972020-04-16 21:02:31 +0530437 "meter-id-in-flow": sq.meterID,
438 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400439 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000440
Neha Sharma96b7bf22020-06-15 10:37:32 +0000441 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530442 log.Fields{
443 "meter-id": sq.meterID,
444 "direction": Direction,
445 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000446
Gamze Abakafee36392019-10-03 11:17:24 +0000447 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700448 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Gamze Abakafee36392019-10-03 11:17:24 +0000449 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700450 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Girish Kumar8f73fe02019-12-09 13:19:37 +0000451 }
452
Girish Gowdraa482f272021-03-24 23:04:19 -0700453 found := false
454 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000455 if sq.flowMetadata != nil {
456 for _, meter := range sq.flowMetadata.Meters {
457 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700458 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700459 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 +0000460 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700461 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530462 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700463 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400464 break
465 }
466 }
467 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000468 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400469 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700470 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530471 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800472 "reason": "Could-not-get-meterbands-from-flowMetadata",
473 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530474 "meter-id": sq.meterID,
475 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400476 }
Gamze Abaka01174422021-03-10 06:55:27 +0000477
478 var TrafficShaping *tp_pb.TrafficShapingInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700479 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
Gamze Abaka01174422021-03-10 06:55:27 +0000480 return olterrors.NewErrInvalidValue(log.Fields{
481 "reason": "invalid-meter-config",
482 "meter-id": sq.meterID,
483 "device-id": f.deviceHandler.device.Id}, nil)
484 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400485
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700486 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000487 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400488
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700489 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530490 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
491 log.Fields{"intf-id": sq.intfID,
492 "direction": sq.direction,
493 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400494 }
495
salmansiddiqui7ac62132019-08-22 03:58:50 +0000496 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400497 * store the meter id on the KV store, for further reference.
498 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700499 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 +0530500 return olterrors.NewErrAdapter("failed-updating-meter-id",
501 log.Fields{"onu-id": sq.onuID,
502 "meter-id": sq.meterID,
503 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400504 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000505 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530506 log.Fields{"direction": Direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700507 "meter-info": meterInfo,
508 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400509 return nil
510}
511
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700512func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700513 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000514
515 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530516 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
517 log.Fields{"intf-id": sq.intfID,
518 "direction": sq.direction,
519 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000520 }
521
Gamze Abakacb0e6772021-06-10 08:32:12 +0000522 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
523 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
524 log.Fields{
525 "direction": sq.direction,
526 "TrafficScheds": TrafficSched,
527 "device-id": f.deviceHandler.device.Id,
528 "intfID": sq.intfID,
529 "onuID": sq.onuID,
530 "uniID": sq.uniID})
531 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
532 IntfId: sq.intfID, OnuId: sq.onuID,
533 UniId: sq.uniID, PortNo: sq.uniPort,
534 TrafficScheds: TrafficSched}); err != nil {
535 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
536 }
537 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
538 "direction": sq.direction,
539 "traffic-queues": trafficQueues,
540 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000541 }
542
543 // On receiving the CreateTrafficQueues request, the driver should create corresponding
544 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000545 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530546 log.Fields{"direction": sq.direction,
547 "traffic-queues": trafficQueues,
548 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530549 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000550 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
551 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000552 TrafficQueues: trafficQueues,
553 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530554 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000555 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000556 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530557 "direction": sq.direction,
558 "traffic-queues": trafficQueues,
559 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000560
Esin Karamanccb714b2019-11-29 15:02:06 +0000561 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700562 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000563 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700564 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 +0000565 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
566 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000567 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000568 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700569 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000570 gemPortID: multicastQueuePerPonPort.GemportId,
571 servicePriority: multicastQueuePerPonPort.Priority,
572 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700573 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000574 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400575 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700576 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400577 return err
578 }
Shrey Baid26912972020-04-16 21:02:31 +0530579
Neha Sharma96b7bf22020-06-15 10:37:32 +0000580 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000581 }
582 }
583 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000584 return nil
585}
586
salmansiddiqui7ac62132019-08-22 03:58:50 +0000587// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530588func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400589
590 var Direction string
591 var SchedCfg *tp_pb.SchedulerConfig
592 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000593 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530594 log.Fields{
595 "direction": sq.direction,
596 "intf-id": sq.intfID,
597 "onu-id": sq.onuID,
598 "uni-id": sq.uniID,
599 "uni-port": sq.uniPort,
600 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000601 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700602 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400603 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000604 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700605 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400606 Direction = "downstream"
607 }
608
Girish Gowdraa482f272021-03-24 23:04:19 -0700609 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 -0400610
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700611 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000612 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000613
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700614 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000615 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530616 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
617 log.Fields{
618 "intf-id": sq.intfID,
619 "direction": sq.direction,
620 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000621 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400622
npujarec5762e2020-01-01 14:08:48 +0530623 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000624 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
625 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000626 TrafficQueues: TrafficQueues,
627 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000628 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530629 log.Fields{
630 "intf-id": sq.intfID,
631 "traffic-queues": TrafficQueues,
632 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400633 }
Gamze Abakacb0e6772021-06-10 08:32:12 +0000634 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400635
Gamze Abakacb0e6772021-06-10 08:32:12 +0000636 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
637 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
638 IntfId: sq.intfID, OnuId: sq.onuID,
639 UniId: sq.uniID, PortNo: sq.uniPort,
640 TrafficScheds: TrafficSched}); err != nil {
641 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
642 log.Fields{
643 "intf-id": sq.intfID,
644 "traffic-schedulers": TrafficSched,
645 "onu-id": sq.onuID,
646 "uni-id": sq.uniID,
647 "uni-port": sq.uniPort}, err)
648 }
649
650 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
651 log.Fields{"device-id": f.deviceHandler.device.Id,
652 "intf-id": sq.intfID,
653 "onu-id": sq.onuID,
654 "uni-id": sq.uniID,
655 "uni-port": sq.uniPort})
656
657 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700658 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
Gamze Abakacb0e6772021-06-10 08:32:12 +0000659 f.resourceMgr.FreeAllocID(ctx, sq.intfID, sq.onuID, sq.uniID, allocID)
660 // Delete the TCONT on the ONU.
661 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
662 tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
663 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
664 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
665 log.Fields{
666 "intf": sq.intfID,
667 "onu-id": sq.onuID,
668 "uni-id": sq.uniID,
669 "device-id": f.deviceHandler.device.Id,
670 "alloc-id": allocID})
671 }
672 }
673 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000674
675 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400676 * delete the meter id on the KV store.
677 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700678 err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400679 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530680 return olterrors.NewErrAdapter("unable-to-remove-meter",
681 log.Fields{
682 "onu": sq.onuID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700683 "device-id": f.deviceHandler.device.Id,
684 "intf-id": sq.intfID,
685 "onu-id": sq.onuID,
686 "uni-id": sq.uniID,
687 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400688 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000689 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530690 log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530691 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700692 "device-id": f.deviceHandler.device.Id,
693 "intf-id": sq.intfID,
694 "onu-id": sq.onuID,
695 "uni-id": sq.uniID,
696 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400697 return err
698}
699
Girish Gowdra197acc12021-08-16 10:59:45 -0700700// We are trying to force remove the schedulers and queues here if one exists for the given key.
701// We ignore any errors encountered in the process. The errors most likely are encountered when
702// the schedulers and queues are already cleared for the given key.
703func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
704
705 var schedCfg *tp_pb.SchedulerConfig
706 var err error
707 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
708 log.Fields{
709 "direction": sq.direction,
710 "intf-id": sq.intfID,
711 "onu-id": sq.onuID,
712 "uni-id": sq.uniID,
713 "uni-port": sq.uniPort,
714 "tp-id": sq.tpID,
715 "device-id": f.deviceHandler.device.Id})
716 if sq.direction == tp_pb.Direction_UPSTREAM {
717 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
718 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
719 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
720 }
721
722 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
723 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
724 TrafficSched[0].TechProfileId = sq.tpID
725
726 // Remove traffic queues. Ignore any errors, just log them.
727 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
728 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
729 "direction": sq.direction,
730 "intf-id": sq.intfID,
731 "onu-id": sq.onuID,
732 "uni-id": sq.uniID,
733 "uni-port": sq.uniPort,
734 "tp-id": sq.tpID,
735 "device-id": f.deviceHandler.device.Id,
736 "err": err})
737 } else {
738 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
739 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
740 UniId: sq.uniID, PortNo: sq.uniPort,
741 TrafficQueues: TrafficQueues,
742 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
743 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
744 "direction": sq.direction,
745 "intf-id": sq.intfID,
746 "onu-id": sq.onuID,
747 "uni-id": sq.uniID,
748 "uni-port": sq.uniPort,
749 "tp-id": sq.tpID,
750 "device-id": f.deviceHandler.device.Id,
751 "err": err})
752
753 } else {
754 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
755 "direction": sq.direction,
756 "intf-id": sq.intfID,
757 "onu-id": sq.onuID,
758 "uni-id": sq.uniID,
759 "uni-port": sq.uniPort,
760 "tp-id": sq.tpID})
761 }
762 }
763
764 // Remove traffic schedulers. Ignore any errors, just log them.
765 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
766 IntfId: sq.intfID, OnuId: sq.onuID,
767 UniId: sq.uniID, PortNo: sq.uniPort,
768 TrafficScheds: TrafficSched}); err != nil {
769 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
770 "direction": sq.direction,
771 "intf-id": sq.intfID,
772 "onu-id": sq.onuID,
773 "uni-id": sq.uniID,
774 "uni-port": sq.uniPort,
775 "tp-id": sq.tpID,
776 "device-id": f.deviceHandler.device.Id,
777 "err": err})
778 } else {
779 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
780 "direction": sq.direction,
781 "intf-id": sq.intfID,
782 "onu-id": sq.onuID,
783 "uni-id": sq.uniID,
784 "uni-port": sq.uniPort,
785 "tp-id": sq.tpID})
786 }
787}
788
Gamze Abakafee36392019-10-03 11:17:24 +0000789// This function allocates tconts and GEM ports for an ONU
khenaidoodc2116e2021-10-19 17:33:19 -0400790func (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 +0000791 var allocIDs []uint32
792 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530793 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530794 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000795 var err error
npujarec5762e2020-01-01 14:08:48 +0530796 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
797 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000798 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530799
Neha Sharma96b7bf22020-06-15 10:37:32 +0000800 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530801 "intf-id": intfID,
802 "onu-id": onuID,
803 "uni-id": uniID,
804 "device-id": f.deviceHandler.device.Id,
805 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530806
Manikkaraj kb1d51442019-07-23 10:41:02 -0400807 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700808 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000809 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000810 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530811 log.Fields{
812 "path": tpPath,
813 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700814 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000815 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530816 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000817 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530818 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700819 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530820 "tp-id": TpID,
821 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000822 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530823 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400824 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700825 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400826 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530827 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000828 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530829 log.Fields{
830 "uni": uni,
831 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530832 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530833 }
Gamze Abakafee36392019-10-03 11:17:24 +0000834
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700835 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700836 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700837 if UsMeterID != 0 {
838 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
839 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
840 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000841 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700842 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700843 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700844 "onu-id": onuID,
845 "uni-id": uniID,
846 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700847 "meter-id": UsMeterID,
848 "device-id": f.deviceHandler.device.Id})
849 return 0, nil, nil
850 }
851 }
852 if DsMeterID != 0 {
853 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
854 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
855 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000856 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700857 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700858 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700859 "onu-id": onuID,
860 "uni-id": uniID,
861 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700862 "meter-id": DsMeterID,
863 "device-id": f.deviceHandler.device.Id})
864 return 0, nil, nil
865 }
866 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700867 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700868 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700869 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700870 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700871 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000872
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700873 if tpInstanceExists {
874 return allocID, gemPortIDs, techProfileInstance
875 }
876
877 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700878 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700879 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000880 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700881 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700882 "intf-id": intfID,
883 "onu-id": onuID,
884 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700885 "alloc-ids": allocIDs,
886 "gemports": allgemPortIDs,
887 "device-id": f.deviceHandler.device.Id})
888 // Send Tconts and GEM ports to KV store
889 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530890 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400891 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700892 // CreateSchedulerQueues for EPON needs to be implemented here
893 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700894 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700895 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700896 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700897 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700898 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700899
900 if tpInstanceExists {
901 return allocID, gemPortIDs, techProfileInstance
902 }
903
904 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700905 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700906 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000907 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700908 log.Fields{
909 "alloc-ids": allocIDs,
910 "gemports": allgemPortIDs,
911 "device-id": f.deviceHandler.device.Id})
912 // Send Tconts and GEM ports to KV store
913 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
914 return allocID, gemPortIDs, techProfileInstance
915 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000916 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700917 log.Fields{
918 "tpInst": tpInst})
919 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530920 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530921}
922
npujarec5762e2020-01-01 14:08:48 +0530923func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530924
Neha Sharma96b7bf22020-06-15 10:37:32 +0000925 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530926 log.Fields{
927 "intf-id": intfID,
928 "onu-id": onuID,
929 "uni-id": uniID,
930 "alloc-id": allocID,
931 "gemport-ids": gemPortIDs,
932 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530933 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530934 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000935 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 +0530936 }
npujarec5762e2020-01-01 14:08:48 +0530937 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000938 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 +0530939 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700940
Neha Sharma96b7bf22020-06-15 10:37:32 +0000941 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 -0400942 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530943 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400944 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530945}
946
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700947func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530948 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000949 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700950 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
951 var err error
952 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
953 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
954 if err != nil || f.techprofile == nil {
955 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
956 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
957 }
958 logger.Debugw(ctx, "init-tech-profile-done",
959 log.Fields{
960 "intf-id": intfID,
961 "device-id": f.deviceHandler.device.Id})
962 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700963 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530964 }
965 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700966 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
967 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 +0530968}
969
Gamze Abaka7650be62021-02-26 10:50:36 +0000970func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Andrea Campanellafaa42152021-10-28 11:50:56 +0530971 flowContext.classifier[PacketTagType] = SingleTag // FIXME: This hardcoding needs to be removed.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000972 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530973 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000974 "uplinkClassifier": flowContext.classifier,
975 "uplinkAction": flowContext.action})
976 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530977 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530978}
979
Gamze Abaka7650be62021-02-26 10:50:36 +0000980func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
981 downlinkClassifier := flowContext.classifier
982 downlinkAction := flowContext.action
983
Andrea Campanellafaa42152021-10-28 11:50:56 +0530984 // TODO: For now mark the PacketTagType as SingleTag when OLT is transparent to VLAN
985 // Per some deployment models, it is also possible that ONU operates on double tagged packets,
986 // so this hardcoding of SingeTag packet-tag-type may be problem for such deployment models.
987 // Need a better way for detection of packet tag type from OpenFlow message.
988 if _, ok := downlinkClassifier[VlanVid]; !ok {
989 downlinkClassifier[PacketTagType] = SingleTag
990 } else {
991 downlinkClassifier[PacketTagType] = DoubleTag
992 downlinkAction[PopVlan] = true
993 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000994 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530995 log.Fields{
996 "downlinkClassifier": downlinkClassifier,
997 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400998 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
999 if vlan, exists := downlinkClassifier[VlanVid]; exists {
1000 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -07001001 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001002 if uint32(metadata.(uint64)) == plt.MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001003 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301004 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001005 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301006 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +00001007 "onu-id": flowContext.onuID,
1008 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001009 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -04001010 }
1011 }
1012 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301013 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001014
Matt Jeannereted16b7c2019-11-01 13:31:35 -04001015 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1016 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +05301017 if ok {
1018 downlinkAction[VlanVid] = dlClVid & 0xfff
Girish Gowdra26f344b2019-10-23 14:39:13 +05301019 }
1020
Gamze Abaka7650be62021-02-26 10:50:36 +00001021 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301022}
1023
Gamze Abaka7650be62021-02-26 10:50:36 +00001024func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001025
Gamze Abaka7650be62021-02-26 10:50:36 +00001026 intfID := flowContext.intfID
1027 onuID := flowContext.onuID
1028 uniID := flowContext.uniID
1029 classifier := flowContext.classifier
1030 action := flowContext.action
1031 allocID := flowContext.allocID
1032 gemPortID := flowContext.gemPortID
1033 tpID := flowContext.tpID
1034 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001035 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301036 log.Fields{
1037 "intf-id": intfID,
1038 "onu-id": onuID,
1039 "uni-id": uniID,
1040 "device-id": f.deviceHandler.device.Id,
1041 "classifier": classifier,
1042 "action": action,
1043 "direction": direction,
1044 "alloc-id": allocID,
1045 "gemport-id": gemPortID,
1046 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001047
1048 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001049 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301050 log.Fields{
1051 "device-id": f.deviceHandler.device.Id,
1052 "intf-id": intfID,
1053 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001054 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301055 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001056 classifierProto, err := makeOpenOltClassifierField(classifier)
1057 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301058 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301059 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001060 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301061 log.Fields{
1062 "classifier": *classifierProto,
1063 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001064 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001065 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301066 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301067 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001068 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301069 log.Fields{
1070 "action": *actionProto,
1071 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001072 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301073 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301074 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001075 log.Fields{
1076 "classifier": classifier,
1077 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301078 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001079 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301080 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001081
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001082 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001083 OnuId: int32(onuID),
1084 UniId: int32(uniID),
1085 FlowId: logicalFlow.Id,
1086 FlowType: direction,
1087 AllocId: int32(allocID),
1088 NetworkIntfId: int32(networkIntfID),
1089 GemportId: int32(gemPortID),
1090 Classifier: classifierProto,
1091 Action: actionProto,
1092 Priority: int32(logicalFlow.Priority),
1093 Cookie: logicalFlow.Cookie,
1094 PortNo: flowContext.portNo,
1095 TechProfileId: tpID,
1096 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1097 PbitToGemport: flowContext.pbitToGem,
1098 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001099 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001100 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001101 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301102 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001103 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301104 log.Fields{"direction": direction,
1105 "device-id": f.deviceHandler.device.Id,
1106 "flow": flow,
1107 "intf-id": intfID,
1108 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001109
David K. Bainbridge794735f2020-02-11 21:01:37 -08001110 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301111}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001112
Gamze Abaka7650be62021-02-26 10:50:36 +00001113func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1114
1115 intfID := flowContext.intfID
1116 onuID := flowContext.onuID
1117 uniID := flowContext.uniID
1118 logicalFlow := flowContext.logicalFlow
1119 classifier := flowContext.classifier
1120 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301121
Neha Sharma96b7bf22020-06-15 10:37:32 +00001122 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301123 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301124 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001125 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301126 "action": action,
1127 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001128 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301129 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301130
1131 // Clear the action map
1132 for k := range action {
1133 delete(action, k)
1134 }
1135
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001136 action[TrapToHost] = true
1137 classifier[UDPSrc] = uint32(68)
1138 classifier[UDPDst] = uint32(67)
1139 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301140
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001141 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001142 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301143 log.Fields{
1144 "device-id": f.deviceHandler.device.Id,
1145 "intf-id": intfID,
1146 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001147 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301148 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301149
Neha Sharma96b7bf22020-06-15 10:37:32 +00001150 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301151 log.Fields{
1152 "ul_classifier": classifier,
1153 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001154 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301155 "intf-id": intfID,
1156 "onu-id": onuID,
1157 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301158
David K. Bainbridge794735f2020-02-11 21:01:37 -08001159 classifierProto, err := makeOpenOltClassifierField(classifier)
1160 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301161 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301162 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001163 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001164 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001165 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301166 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301167 }
1168
David K. Bainbridge794735f2020-02-11 21:01:37 -08001169 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001170 OnuId: int32(onuID),
1171 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001172 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001173 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001174 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001175 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001176 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301177 Classifier: classifierProto,
1178 Action: actionProto,
1179 Priority: int32(logicalFlow.Priority),
1180 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001181 PortNo: flowContext.portNo,
1182 TechProfileId: flowContext.tpID,
1183 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1184 PbitToGemport: flowContext.pbitToGem,
1185 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001186 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001187 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001188 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001189 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001190 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301191 log.Fields{
1192 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001193 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301194 "intf-id": intfID,
1195 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301196
David K. Bainbridge794735f2020-02-11 21:01:37 -08001197 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301198}
1199
Esin Karamanae41e2b2019-12-17 18:13:13 +00001200//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001201func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1202 delete(flowContext.classifier, VlanVid)
1203 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001204}
1205
1206//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001207func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1208
1209 intfID := flowContext.intfID
1210 onuID := flowContext.onuID
1211 uniID := flowContext.uniID
1212 logicalFlow := flowContext.logicalFlow
1213 classifier := flowContext.classifier
1214 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001215
Neha Sharma96b7bf22020-06-15 10:37:32 +00001216 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001217 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301218 return olterrors.NewErrNotFound("nni-interface-id",
1219 log.Fields{
1220 "classifier": classifier,
1221 "action": action,
1222 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001223 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001224 }
1225
1226 // Clear the action map
1227 for k := range action {
1228 delete(action, k)
1229 }
1230
1231 action[TrapToHost] = true
1232 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001233
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001234 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001235 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001236 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001237 }
1238
Neha Sharma96b7bf22020-06-15 10:37:32 +00001239 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301240 log.Fields{
1241 "ul_classifier": classifier,
1242 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001243 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301244 "device-id": f.deviceHandler.device.Id,
1245 "intf-id": intfID,
1246 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001247
David K. Bainbridge794735f2020-02-11 21:01:37 -08001248 classifierProto, err := makeOpenOltClassifierField(classifier)
1249 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301250 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001251 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001252 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301253 log.Fields{
1254 "classifier": *classifierProto,
1255 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001256 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001257 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301258 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001259 }
1260
David K. Bainbridge794735f2020-02-11 21:01:37 -08001261 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001262 OnuId: int32(onuID),
1263 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001264 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001265 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001266 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001267 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001268 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001269 Classifier: classifierProto,
1270 Action: actionProto,
1271 Priority: int32(logicalFlow.Priority),
1272 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001273 PortNo: flowContext.portNo,
1274 TechProfileId: flowContext.tpID,
1275 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1276 PbitToGemport: flowContext.pbitToGem,
1277 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001278 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001279
David K. Bainbridge794735f2020-02-11 21:01:37 -08001280 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001281 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 -08001282 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001283
David K. Bainbridge794735f2020-02-11 21:01:37 -08001284 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001285}
1286
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001287// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001288func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1289 intfID := flowContext.intfID
1290 onuID := flowContext.onuID
1291 uniID := flowContext.uniID
1292 portNo := flowContext.portNo
1293 allocID := flowContext.allocID
1294 gemPortID := flowContext.gemPortID
1295 logicalFlow := flowContext.logicalFlow
1296 classifier := flowContext.classifier
1297 action := flowContext.action
1298
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001299 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301300 log.Fields{
1301 "intf-id": intfID,
1302 "onu-id": onuID,
1303 "port-no": portNo,
1304 "alloc-id": allocID,
1305 "gemport-id": gemPortID,
1306 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001307 "flow": logicalFlow,
1308 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301309
1310 uplinkClassifier := make(map[string]interface{})
1311 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301312
manikkaraj kbf256be2019-03-25 00:13:48 +05301313 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001314 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001315 uplinkClassifier[PacketTagType] = SingleTag
1316 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001317 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301318 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001319 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001320 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001321 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301322 "device-id": f.deviceHandler.device.Id,
1323 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001324 "intf-id": intfID,
1325 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001326 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301327 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001328 //Add Uplink EthType Flow
1329 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301330 log.Fields{
1331 "ul_classifier": uplinkClassifier,
1332 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001333 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301334 "device-id": f.deviceHandler.device.Id,
1335 "intf-id": intfID,
1336 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301337
David K. Bainbridge794735f2020-02-11 21:01:37 -08001338 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1339 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301340 return olterrors.NewErrInvalidValue(log.Fields{
1341 "classifier": uplinkClassifier,
1342 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301343 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001344 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301345 log.Fields{
1346 "classifier": *classifierProto,
1347 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001348 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001349 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301350 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301351 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001352 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301353 log.Fields{
1354 "action": *actionProto,
1355 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001356 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301357 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301358 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001359 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301360 "action": action,
1361 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001362 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301363 }
1364
David K. Bainbridge794735f2020-02-11 21:01:37 -08001365 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001366 OnuId: int32(onuID),
1367 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001368 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001369 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001370 AllocId: int32(allocID),
1371 NetworkIntfId: int32(networkIntfID),
1372 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301373 Classifier: classifierProto,
1374 Action: actionProto,
1375 Priority: int32(logicalFlow.Priority),
1376 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001377 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001378 TechProfileId: flowContext.tpID,
1379 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1380 PbitToGemport: flowContext.pbitToGem,
1381 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001382 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001383 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001384 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001385 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001386 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301387 log.Fields{
1388 "device-id": f.deviceHandler.device.Id,
1389 "onu-id": onuID,
1390 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001391 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301392 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001393
David K. Bainbridge794735f2020-02-11 21:01:37 -08001394 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301395}
1396
David K. Bainbridge794735f2020-02-11 21:01:37 -08001397func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001398 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001399
1400 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1401 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1402 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001403 if vlanID != ReservedVlan {
1404 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001405 classifier.OVid = vid
1406 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301407 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301408 // 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 -07001409 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1410 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301411 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1412 // If OLT is using transparent tag mechanism, then it classifies whatever tag it sees to/from ONU which
1413 //is OVid from the perspective of the OLT. When OLT also places or pops the outer tag, then classifierInfo[Metadata]
1414 // becomes the IVid.
1415 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1416 if vid != ReservedVlan {
1417 classifier.IVid = vid
1418 }
1419 } else {
1420 if vid != ReservedVlan {
1421 classifier.OVid = vid
1422 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001423 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301424 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301425 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001426 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301427 classifier.OPbits = vlanPcp
1428 } else {
1429 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301430 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001431 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1432 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1433 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1434 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001435 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001436 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1437 classifier.PktTagType = pktTagType
1438
1439 switch pktTagType {
1440 case SingleTag:
1441 case DoubleTag:
1442 case Untagged:
1443 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001444 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301445 }
1446 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001447 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301448}
1449
Gamze Abaka724d0852020-03-18 12:10:24 +00001450func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001451 var actionCmd openoltpb2.ActionCmd
1452 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301453 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001454 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301455 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001456 if _, ok := actionInfo[VlanPcp]; ok {
1457 action.Cmd.RemarkInnerPbits = true
1458 action.IPbits = actionInfo[VlanPcp].(uint32)
1459 if _, ok := actionInfo[VlanVid]; ok {
1460 action.Cmd.TranslateInnerTag = true
1461 action.IVid = actionInfo[VlanVid].(uint32)
1462 }
1463 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001464 } else if _, ok := actionInfo[PushVlan]; ok {
1465 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301466 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001467 if _, ok := actionInfo[VlanPcp]; ok {
1468 action.OPbits = actionInfo[VlanPcp].(uint32)
1469 action.Cmd.RemarkOuterPbits = true
1470 if _, ok := classifierInfo[VlanVid]; ok {
1471 action.IVid = classifierInfo[VlanVid].(uint32)
1472 action.Cmd.TranslateInnerTag = true
1473 }
1474 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001475 } else if _, ok := actionInfo[TrapToHost]; ok {
1476 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301477 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301478 // When OLT is transparent to vlans no-action is valid.
1479 /*
1480 else {
1481 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1482 }
1483 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001484 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301485}
1486
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001487// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001488func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001489 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301490}
1491
Gamze Abakafee36392019-10-03 11:17:24 +00001492// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001493// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1494// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1495// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1496// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1497// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1498// because it was observed that if the ONU device was deleted too soon after the flows were
1499// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1500// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1501// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001502func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301503 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001504 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1505
Gamze Abakafee36392019-10-03 11:17:24 +00001506 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001507
1508 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001509 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001510 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1511 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
1512 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1513 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1514 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1515 log.Fields{
1516 "tp-id": tpID,
1517 "path": tpPath})
1518 }
1519 switch tpInstance := tpInst.(type) {
1520 case *tp_pb.TechProfileInstance:
1521 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1522 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1523 }
1524 // Force cleanup scheduler/queues -- end
1525
1526 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301527 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001528 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301529 // return err
1530 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001531 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001532 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 +00001533 }
1534 return nil
1535}
1536
1537// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301538func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001539 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001540 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001541 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001542 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301543 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1544 log.Fields{
1545 "tp-id": tpID,
1546 "uni-port-name": uniPortName,
1547 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001548 }
1549 return nil
1550}
1551
David K. Bainbridge794735f2020-02-11 21:01:37 -08001552func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001553
1554 var intfID uint32
1555 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1556 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1557 */
1558 if deviceFlow.AccessIntfId != -1 {
1559 intfID = uint32(deviceFlow.AccessIntfId)
1560 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001561 // We need to log the valid interface ID.
1562 // 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 +00001563 intfID = uint32(deviceFlow.NetworkIntfId)
1564 }
1565
Neha Sharma96b7bf22020-06-15 10:37:32 +00001566 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301567 "flow": *deviceFlow,
1568 "device-id": f.deviceHandler.device.Id,
1569 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001570 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001571
1572 st, _ := status.FromError(err)
1573 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001574 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001575 "err": err,
1576 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301577 "device-id": f.deviceHandler.device.Id,
1578 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001579 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301580 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001581
1582 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001583 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301584 log.Fields{"err": err,
1585 "device-flow": deviceFlow,
1586 "device-id": f.deviceHandler.device.Id,
1587 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001588 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001589 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001590 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301591 log.Fields{
1592 "flow": *deviceFlow,
1593 "device-id": f.deviceHandler.device.Id,
1594 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001595
1596 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1597 if deviceFlow.AccessIntfId != -1 {
1598 // No need to register the flow if it is a trap on nni flow.
1599 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1600 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1601 return err
1602 }
1603 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001604 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001605}
1606
Neha Sharma96b7bf22020-06-15 10:37:32 +00001607func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1608 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301609 log.Fields{
1610 "flow": *deviceFlow,
1611 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001612 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001613 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001614 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001615 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301616 log.Fields{
1617 "err": err,
1618 "deviceFlow": deviceFlow,
1619 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001620 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001621 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001622 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001623 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001624
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001625 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001626 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001627 "of-flow-id": ofFlowID,
1628 "flow": *deviceFlow,
1629 "device-id": f.deviceHandler.device.Id,
1630 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001631 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301632}
1633
David K. Bainbridge794735f2020-02-11 21:01:37 -08001634func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001635
1636 classifierInfo := make(map[string]interface{})
1637 actionInfo := make(map[string]interface{})
1638
1639 classifierInfo[EthType] = uint32(LldpEthType)
1640 classifierInfo[PacketTagType] = Untagged
1641 actionInfo[TrapToHost] = true
1642
1643 // LLDP flow is installed to trap LLDP packets on the NNI port.
1644 // We manage flow_id resource pool on per PON port basis.
1645 // Since this situation is tricky, as a hack, we pass the NNI port
1646 // index (network_intf_id) as PON port Index for the flow_id resource
1647 // pool. Also, there is no ONU Id available for trapping LLDP packets
1648 // on NNI port, use onu_id as -1 (invalid)
1649 // ****************** CAVEAT *******************
1650 // This logic works if the NNI Port Id falls within the same valid
1651 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1652 // we need to have a re-look at this.
1653 // *********************************************
1654
1655 var onuID = -1
1656 var uniID = -1
1657 var gemPortID = -1
1658
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001659 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001660 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301661 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001662 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001663 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001664 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001665 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001666 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001667
David K. Bainbridge794735f2020-02-11 21:01:37 -08001668 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1669 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301670 return olterrors.NewErrInvalidValue(
1671 log.Fields{
1672 "classifier": classifierInfo,
1673 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001674 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001675 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301676 log.Fields{
1677 "classifier": *classifierProto,
1678 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001679 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001680 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301681 return olterrors.NewErrInvalidValue(
1682 log.Fields{
1683 "action": actionInfo,
1684 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001685 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001686 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301687 log.Fields{
1688 "action": *actionProto,
1689 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001690
1691 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1692 OnuId: int32(onuID), // OnuId not required
1693 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001694 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001695 FlowType: Downstream,
1696 NetworkIntfId: int32(networkInterfaceID),
1697 GemportId: int32(gemPortID),
1698 Classifier: classifierProto,
1699 Action: actionProto,
1700 Priority: int32(flow.Priority),
1701 Cookie: flow.Cookie,
1702 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001703 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001704 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301705 log.Fields{
1706 "flow": downstreamflow,
1707 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001708 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001709 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301710 log.Fields{
1711 "device-id": f.deviceHandler.device.Id,
1712 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001713 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001714
David K. Bainbridge794735f2020-02-11 21:01:37 -08001715 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301716}
1717
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001718func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1719 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001720}
1721
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001722//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001723func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001724 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1725 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1726 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001727 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301728 log.Fields{
1729 "intf-id": intfID,
1730 "onu-id": onuID,
1731 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001732 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001733 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301734 return nil, olterrors.NewErrNotFound("onu-child-device",
1735 log.Fields{
1736 "onu-id": onuID,
1737 "intf-id": intfID,
1738 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001739 }
khenaidoo106c61a2021-08-11 18:05:46 -04001740 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 -07001741 //better to ad the device to cache here.
1742 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1743 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001744 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301745 log.Fields{
1746 "intf-id": intfID,
1747 "onu-id": onuID,
1748 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001749 }
1750
1751 return onuDev.(*OnuDevice), nil
1752}
1753
1754//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001755func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1756 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301757 log.Fields{
1758 "pon-port": intfID,
1759 "onu-id": onuID,
1760 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001761 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001762 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001763 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301764 return nil, olterrors.NewErrNotFound("onu",
1765 log.Fields{
1766 "interface-id": parentPortNo,
1767 "onu-id": onuID,
1768 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001769 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301770 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001771 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301772 log.Fields{
1773 "device-id": f.deviceHandler.device.Id,
1774 "child_device_id": onuDevice.Id,
1775 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301776 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301777}
1778
Neha Sharma96b7bf22020-06-15 10:37:32 +00001779func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1780 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301781 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001782 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301783 log.Fields{
1784 "intf-id": intfID,
1785 "onu-id": onuID,
1786 "uni-id": uniID,
1787 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001788 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301789 }
1790
khenaidoodc2116e2021-10-19 17:33:19 -04001791 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001792 DeviceId: onuDev.deviceID,
1793 UniId: uniID,
1794 TpInstancePath: tpPath,
1795 GemPortId: gemPortID,
1796 }
1797 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1798
1799 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301800 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1801 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001802 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1803 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301804 "onu-id": onuDev.deviceID,
1805 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001806 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301807 }
khenaidoo106c61a2021-08-11 18:05:46 -04001808
Neha Sharma96b7bf22020-06-15 10:37:32 +00001809 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301810 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001811 "msg": delGemPortMsg,
1812 "from-adapter": f.deviceHandler.device.Type,
1813 "to-adapter": onuDev.deviceType,
1814 "device-id": f.deviceHandler.device.Id,
1815 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301816 return nil
1817}
1818
Neha Sharma96b7bf22020-06-15 10:37:32 +00001819func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1820 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301821 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001822 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301823 log.Fields{
1824 "intf-id": intfID,
1825 "onu-id": onuID,
1826 "uni-id": uniID,
1827 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001828 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301829 }
1830
khenaidoodc2116e2021-10-19 17:33:19 -04001831 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001832 DeviceId: onuDev.deviceID,
1833 UniId: uniID,
1834 TpInstancePath: tpPath,
1835 AllocId: allocID,
1836 }
1837
Neha Sharma96b7bf22020-06-15 10:37:32 +00001838 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301839 log.Fields{
1840 "msg": *delTcontMsg,
1841 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001842
1843 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301844 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1845 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001846 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1847 "to-adapter": onuDev.adapterEndpoint,
1848 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301849 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001850 "device-id": f.deviceHandler.device.Id}, err)
1851
Girish Gowdra6b130582019-11-20 16:45:20 +05301852 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001853 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301854 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001855 "msg": delTcontMsg,
1856 "device-id": f.deviceHandler.device.Id,
1857 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301858 return nil
1859}
1860
Girish Gowdrac3037402020-01-22 20:29:53 +05301861// Once the gemport is released for a given onu, it also has to be cleared from local cache
1862// which was used for deriving the gemport->logicalPortNo during packet-in.
1863// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1864// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001865func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001866 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301867 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001868 "gem-port-id": gemPortID,
1869 "intf-id": intfID,
1870 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001871 "device-id": f.deviceHandler.device.Id})
1872 f.onuGemInfoLock.RLock()
1873 onugem, ok := f.onuGemInfoMap[onuID]
1874 f.onuGemInfoLock.RUnlock()
1875 if !ok {
1876 logger.Warnw(ctx, "onu gem info already cleared from cache", log.Fields{
1877 "gem-port-id": gemPortID,
1878 "intf-id": intfID,
1879 "onu-id": onuID,
1880 "device-id": f.deviceHandler.device.Id})
1881 return
1882 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001883deleteLoop:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001884 for j, gem := range onugem.GemPorts {
1885 // If the gemport is found, delete it from local cache.
1886 if gem == gemPortID {
1887 onugem.GemPorts = append(onugem.GemPorts[:j], onugem.GemPorts[j+1:]...)
1888 f.onuGemInfoLock.Lock()
1889 f.onuGemInfoMap[onuID] = onugem
1890 f.onuGemInfoLock.Unlock()
1891 logger.Infow(ctx, "removed-gemport-from-local-cache",
1892 log.Fields{
1893 "intf-id": intfID,
1894 "onu-id": onuID,
1895 "deletedgemport-id": gemPortID,
1896 "gemports": onugem.GemPorts,
1897 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001898 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301899 }
1900 }
1901}
1902
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301903//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001904// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001905func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Girish Gowdra82c80982021-03-26 16:22:02 -07001906 gemPortID int32, flowID uint64, portNum uint32, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001907
Girish Gowdraa482f272021-03-24 23:04:19 -07001908 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1909 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001910 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1911 log.Fields{
1912 "tpPath": tpPath,
1913 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001914
1915 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1916
1917 if used {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001918 f.gemToFlowIDsKey.RLock()
1919 flowIDs := f.gemToFlowIDs[uint32(gemPortID)]
1920 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001921
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001922 for i, flowIDinMap := range flowIDs {
1923 if flowIDinMap == flowID {
1924 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001925 f.gemToFlowIDsKey.Lock()
1926 f.gemToFlowIDs[uint32(gemPortID)] = flowIDs
1927 f.gemToFlowIDsKey.Unlock()
1928 // everytime gemToFlowIDs cache is updated the same should be updated
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001929 // in kv store by calling UpdateFlowIDsForGem
Girish Gowdraa482f272021-03-24 23:04:19 -07001930 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001931 return err
1932 }
1933 break
1934 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001935 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001936 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1937 log.Fields{
1938 "gemport-id": gemPortID,
1939 "usedByFlows": flowIDs,
1940 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001941
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001942 return nil
1943 }
1944 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
Girish Gowdraa482f272021-03-24 23:04:19 -07001945 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001946 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), uint32(gemPortID)) // ignore error and proceed.
1947 //everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001948 // by calling DeleteFlowIDsForGem
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001949 f.gemToFlowIDsKey.Lock()
1950 delete(f.gemToFlowIDs, uint32(gemPortID))
1951 f.gemToFlowIDsKey.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001952
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001953 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1954
1955 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001956
Mahir Gunyel199570a2021-07-04 15:39:36 -07001957 //First remove TCONT from child if needed. Then remove the GEM.
1958 //It is expected from child to clean ani side conf if all GEMs of TP are deleted.
1959 //Before this, ensure that the related TCONT deletions are informed to child.
1960 //Refer to VOL-4215.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001961 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001962 if err != nil || techprofileInst == nil {
1963 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1964 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1965 if childDevice == nil {
1966 // happens when subscriber un-provision is immediately followed by child device delete
1967 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1968 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1969 return nil
1970 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001971 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1972 log.Fields{
1973 "tp-id": tpID,
1974 "path": tpPath}, err)
1975 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001976 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001977 case *tp_pb.TechProfileInstance:
Gamze Abakacb0e6772021-06-10 08:32:12 +00001978 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst, uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001979 if !ok {
Girish Gowdraa482f272021-03-24 23:04:19 -07001980 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001981 logger.Warn(ctx, err)
1982 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001983 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001984 logger.Warn(ctx, err)
1985 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001986 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001987 logger.Warn(ctx, err)
1988 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001989 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001990 logger.Warn(ctx, err)
1991 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001992 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001993 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07001994 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001995 logger.Warn(ctx, err)
1996 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001997 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001998 logger.Warn(ctx, err)
1999 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002000 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002001 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002002 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002003 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302004 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002005 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302006 "onu-id": onuID,
2007 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002008 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002009 "alloc-id": techprofileInst.AllocId,
2010 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002011 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002012 default:
2013 logger.Errorw(ctx, "error-unknown-tech",
2014 log.Fields{
2015 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002016 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002017
Mahir Gunyel199570a2021-07-04 15:39:36 -07002018 // Delete the gem port on the ONU. Send Gem Removal After TCONT removal.
2019 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
2020 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2021 log.Fields{
2022 "err": err,
2023 "intfID": intfID,
2024 "onu-id": onuID,
2025 "uni-id": uniID,
2026 "device-id": f.deviceHandler.device.Id,
2027 "gemport-id": gemPortID})
2028 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302029 return nil
2030}
2031
David K. Bainbridge794735f2020-02-11 21:01:37 -08002032// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002033func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002034 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302035 log.Fields{
2036 "flowDirection": flowDirection,
2037 "flow": *flow,
2038 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002039
2040 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002041 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002042 }
2043
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302044 classifierInfo := make(map[string]interface{})
2045
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002046 portNum, Intf, onu, uni, inPort, ethType, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302047 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002048 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002049 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302050 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302051
David K. Bainbridge794735f2020-02-11 21:01:37 -08002052 onuID := int32(onu)
2053 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002054 tpID, err := getTpIDFromFlow(ctx, flow)
2055 if err != nil {
2056 return olterrors.NewErrNotFound("tp-id",
2057 log.Fields{
2058 "flow": flow,
2059 "intf-id": Intf,
2060 "onu-id": onuID,
2061 "uni-id": uniID,
2062 "device-id": f.deviceHandler.device.Id}, err)
2063 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302064
2065 for _, field := range flows.GetOfbFields(flow) {
2066 if field.Type == flows.IP_PROTO {
2067 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002068 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302069 }
2070 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002071 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302072 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002073 "flow-id": flow.Id,
2074 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302075 "onu-id": onuID,
2076 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302077
2078 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2079 onuID = -1
2080 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002081 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002082 Intf, err = plt.IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002083 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002084 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002085 log.Fields{
2086 "port-number": inPort,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002087 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002088 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002089 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302090 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002091
2092 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2093 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002094 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2095 return err
2096 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002097
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002098 f.flowIDToGemsLock.Lock()
2099 gems, ok := f.flowIDToGems[flow.Id]
2100 if !ok {
2101 logger.Errorw(ctx, "flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id})
2102 f.flowIDToGemsLock.Unlock()
2103 return olterrors.NewErrNotFound("flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id}, nil)
2104 }
2105 copyOfGems := make([]uint32, len(gems))
2106 _ = copy(copyOfGems, gems)
2107 // Delete the flow-id to gemport list entry from the map now the flow is deleted.
2108 delete(f.flowIDToGems, flow.Id)
2109 f.flowIDToGemsLock.Unlock()
2110
2111 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": copyOfGems})
2112 for _, gem := range copyOfGems {
2113 if err = f.clearResources(ctx, Intf, onuID, uniID, int32(gem), flow.Id, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002114 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002115 "flow-id": flow.Id,
2116 "device-id": f.deviceHandler.device.Id,
2117 "onu-id": onuID,
2118 "intf": Intf,
2119 "gem": gem,
2120 "err": err,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002121 })
2122 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302123 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302124 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002125
Girish Gowdra82c80982021-03-26 16:22:02 -07002126 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2127 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2128 return err
2129 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002130 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002131}
2132
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002133//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002134func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002135
Matteo Scandolof16389e2021-05-18 00:47:08 +00002136 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302137 var direction string
2138 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002139
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302140 for _, action := range flows.GetActions(flow) {
2141 if action.Type == flows.OUTPUT {
2142 if out := action.GetOutput(); out != nil {
2143 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002144 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302145 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002146 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002147 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002148 }
2149 }
2150 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002151
2152 if flows.HasGroup(flow) {
2153 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002154 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002155 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302156 direction = Upstream
2157 } else {
2158 direction = Downstream
2159 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302160
Girish Gowdracefae192020-03-19 18:14:10 -07002161 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002162 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002163
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002164 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002165}
2166
Esin Karamanae41e2b2019-12-17 18:13:13 +00002167//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2168func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002169 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002170 if ethType, ok := classifierInfo[EthType]; ok {
2171 if ethType.(uint32) == IPv4EthType {
2172 if ipProto, ok := classifierInfo[IPProto]; ok {
2173 if ipProto.(uint32) == IgmpProto {
2174 return true
2175 }
2176 }
2177 }
2178 }
2179 }
2180 return false
2181}
2182
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002183// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002184func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002185 // Step1 : Fill flowControlBlock
2186 // Step2 : Push the flowControlBlock to ONU channel
2187 // Step3 : Wait on response channel for response
2188 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002189 startTime := time.Now()
2190 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002191 errChan := make(chan error)
2192 flowCb := flowControlBlock{
2193 ctx: ctx,
2194 addFlow: addFlow,
2195 flow: flow,
2196 flowMetadata: flowMetadata,
2197 errChan: &errChan,
2198 }
2199 inPort, outPort := getPorts(flow)
2200 var onuID uint32
2201 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002202 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002203 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002204 if f.flowHandlerRoutineActive[onuID] {
2205 // inPort or outPort is InvalidPort for trap-from-nni flows.
2206 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2207 // Send the flowCb on the ONU flow channel
2208 f.incomingFlows[onuID] <- flowCb
2209 // Wait on the channel for flow handlers return value
2210 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002211 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002212 return err
2213 }
2214 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2215 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002216}
2217
2218// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2219// 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 -07002220func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002221 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002222 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002223 // block on the channel to receive an incoming flow
2224 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002225 case flowCb := <-subscriberFlowChannel:
2226 if flowCb.addFlow {
2227 logger.Info(flowCb.ctx, "adding-flow-start")
2228 startTime := time.Now()
2229 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2230 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2231 // Pass the return value over the return channel
2232 *flowCb.errChan <- err
2233 } else {
2234 logger.Info(flowCb.ctx, "removing-flow-start")
2235 startTime := time.Now()
2236 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2237 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2238 // Pass the return value over the return channel
2239 *flowCb.errChan <- err
2240 }
2241 case <-stopHandler:
2242 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2243 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002244 }
2245 }
2246}
2247
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002248// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
2249func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context) {
2250 for i, v := range f.stopFlowHandlerRoutine {
2251 if f.flowHandlerRoutineActive[i] {
2252 v <- true
2253 }
2254 }
2255 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2256}
2257
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002258// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302259// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002260func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002261 classifierInfo := make(map[string]interface{})
2262 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002263 var UsMeterID uint32
2264 var DsMeterID uint32
2265
Neha Sharma96b7bf22020-06-15 10:37:32 +00002266 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302267 log.Fields{
2268 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002269 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002270 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002271
Neha Sharma96b7bf22020-06-15 10:37:32 +00002272 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002273 if err != nil {
2274 // Error logging is already done in the called function
2275 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002276 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302277 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002278
Esin Karamanccb714b2019-11-29 15:02:06 +00002279 if flows.HasGroup(flow) {
2280 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002281 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002282 }
2283
manikkaraj k17652a72019-05-06 09:06:36 -04002284 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002285 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002286 if err != nil {
2287 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002288 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002289 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002290
Neha Sharma96b7bf22020-06-15 10:37:32 +00002291 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302292 log.Fields{
2293 "classifierinfo_inport": classifierInfo[InPort],
2294 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002295 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002296
Humera Kouser94d7a842019-08-25 19:04:32 -04002297 if ethType, ok := classifierInfo[EthType]; ok {
2298 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002299 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002300 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002301 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002302 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002303 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002304 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2305 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2306 }
2307 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002308 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002309 if ipProto, ok := classifierInfo[IPProto]; ok {
2310 if ipProto.(uint32) == IPProtoDhcp {
2311 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302312 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002313 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002314 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002315 }
2316 }
2317 }
2318 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002319 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002320 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002321 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002322 }
A R Karthick1f85b802019-10-11 05:06:05 +00002323
npujarec5762e2020-01-01 14:08:48 +05302324 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002325 // also update flowmgr cache
2326 f.onuGemInfoLock.Lock()
2327 onugem, ok := f.onuGemInfoMap[onuID]
2328 if ok {
2329 found := false
2330 for _, uni := range onugem.UniPorts {
2331 if uni == portNo {
2332 found = true
2333 break
2334 }
2335 }
2336 if !found {
2337 onugem.UniPorts = append(onugem.UniPorts, portNo)
2338 f.onuGemInfoMap[onuID] = onugem
2339 logger.Infow(ctx, "added uni port to onugem cache", log.Fields{"uni": portNo})
2340 }
2341 }
2342 f.onuGemInfoLock.Unlock()
A R Karthick1f85b802019-10-11 05:06:05 +00002343
Neha Sharma96b7bf22020-06-15 10:37:32 +00002344 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002345 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302346 return olterrors.NewErrNotFound("tpid-for-flow",
2347 log.Fields{
2348 "flow": flow,
2349 "intf-id": IntfID,
2350 "onu-id": onuID,
2351 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002352 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002353 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302354 log.Fields{
2355 "tp-id": TpID,
2356 "intf-id": intfID,
2357 "onu-id": onuID,
2358 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002359 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002360 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002361 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002362 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002363 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002364 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002365
2366 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002367 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002368}
Girish Gowdra3d633032019-12-10 16:37:05 +05302369
Esin Karamanccb714b2019-11-29 15:02:06 +00002370// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002371func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302372 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002373 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302374 "classifier-info": classifierInfo,
2375 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002376
Esin Karaman65409d82020-03-18 10:58:18 +00002377 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002378 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002379 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002380 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002381
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002382 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002383
David K. Bainbridge794735f2020-02-11 21:01:37 -08002384 onuID := NoneOnuID
2385 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002386
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002387 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002388 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002389 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002390 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002391 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2392 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002393 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002394 }
2395 groupID := actionInfo[GroupID].(uint32)
2396 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002397 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002398 FlowType: Multicast,
2399 NetworkIntfId: int32(networkInterfaceID),
2400 GroupId: groupID,
2401 Classifier: classifierProto,
2402 Priority: int32(flow.Priority),
2403 Cookie: flow.Cookie}
2404
Kent Hagermane6ff1012020-07-14 15:07:53 -04002405 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002406 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002407 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002408 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002409 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002410 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002411 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002412 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002413 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002414 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002415 //cached group can be removed now
2416 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002417 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002418 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002419 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002420
David K. Bainbridge794735f2020-02-11 21:01:37 -08002421 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002422}
2423
Esin Karaman65409d82020-03-18 10:58:18 +00002424//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2425func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2426 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002427 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002428 if err != nil {
2429 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2430 }
2431 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002432 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002433
2434 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2435 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002436}
2437
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002438//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002439func (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 -07002440
Neha Sharma96b7bf22020-06-15 10:37:32 +00002441 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302442 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002443 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302444 log.Fields{
2445 "intf-id": intfID,
2446 "onu-id": onuID,
2447 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002448 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302449 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002450 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002451
Neha Sharma96b7bf22020-06-15 10:37:32 +00002452 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002453 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002454 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002455 UniId: uniID,
2456 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002457 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002458 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002459 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002460
2461 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2462 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302463 return olterrors.NewErrCommunication("send-techprofile-download-request",
2464 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002465 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302466 "to-adapter": onuDev.deviceType,
2467 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002468 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002469 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002470 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302471 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302472}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002473
Girish Gowdra197acc12021-08-16 10:59:45 -07002474//AddOnuInfoToFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2475func (f *OpenOltFlowMgr) AddOnuInfoToFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302476
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002477 f.onuGemInfoLock.RLock()
2478 _, ok := f.onuGemInfoMap[onuID]
2479 f.onuGemInfoLock.RUnlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002480 // If the ONU already exists in onuGemInfo list, nothing to do
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002481 if ok {
2482 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2483 log.Fields{"onuID": onuID,
2484 "serialNum": serialNum})
2485 return nil
Girish Gowdra9602eb42020-09-09 15:50:39 -07002486 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002487
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002488 onuGemInfo := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2489 f.onuGemInfoLock.Lock()
2490 f.onuGemInfoMap[onuID] = &onuGemInfo
2491 f.onuGemInfoLock.Unlock()
2492 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onuID, onuGemInfo); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002493 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302494 }
Girish Gowdra197acc12021-08-16 10:59:45 -07002495 logger.Infow(ctx, "added-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302496 log.Fields{
2497 "intf-id": intfID,
2498 "onu-id": onuID,
2499 "serial-num": serialNum,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002500 "onu": onuGemInfo,
Shrey Baid26912972020-04-16 21:02:31 +05302501 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002502 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002503}
2504
Girish Gowdra197acc12021-08-16 10:59:45 -07002505//RemoveOnuInfoFromFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2506func (f *OpenOltFlowMgr) RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32) error {
2507
2508 f.onuGemInfoLock.Lock()
2509 delete(f.onuGemInfoMap, onuID)
2510 f.onuGemInfoLock.Unlock()
2511
2512 if err := f.resourceMgr.DelOnuGemInfo(ctx, intfID, onuID); err != nil {
2513 return err
2514 }
2515 logger.Infow(ctx, "deleted-onuinfo",
2516 log.Fields{
2517 "intf-id": intfID,
2518 "onu-id": onuID,
2519 "device-id": f.deviceHandler.device.Id})
2520 return nil
2521}
2522
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302523//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302524func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002525
Neha Sharma96b7bf22020-06-15 10:37:32 +00002526 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302527 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002528 "gem-port-id": gemPort,
2529 "intf-id": intfID,
2530 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002531 "device-id": f.deviceHandler.device.Id})
2532 f.onuGemInfoLock.RLock()
2533 onugem, ok := f.onuGemInfoMap[onuID]
2534 f.onuGemInfoLock.RUnlock()
2535 if !ok {
2536 logger.Warnw(ctx, "onu gem info is missing", log.Fields{
2537 "gem-port-id": gemPort,
2538 "intf-id": intfID,
2539 "onu-id": onuID,
2540 "device-id": f.deviceHandler.device.Id})
2541 return
2542 }
2543
2544 if onugem.OnuID == onuID {
2545 // check if gem already exists , else update the cache and kvstore
2546 for _, gem := range onugem.GemPorts {
2547 if gem == gemPort {
2548 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2549 log.Fields{
2550 "gem": gemPort,
2551 "device-id": f.deviceHandler.device.Id})
2552 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302553 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302554 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002555 onugem.GemPorts = append(onugem.GemPorts, gemPort)
2556 f.onuGemInfoLock.Lock()
2557 f.onuGemInfoMap[onuID] = onugem
2558 f.onuGemInfoLock.Unlock()
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002559 logger.Debugw(ctx, "updated onu gem info from cache", log.Fields{"onugem": onugem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002560 } else {
2561 logger.Warnw(ctx, "mismatched onu id", log.Fields{
2562 "gem-port-id": gemPort,
2563 "intf-id": intfID,
2564 "onu-id": onuID,
2565 "device-id": f.deviceHandler.device.Id})
2566 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302567 }
npujarec5762e2020-01-01 14:08:48 +05302568 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302569 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002570 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302571 log.Fields{
2572 "intf-id": intfID,
2573 "onu-id": onuID,
2574 "gemPort": gemPort,
2575 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002576 return
2577 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002578 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302579 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002580 "gem-port-id": gemPort,
2581 "intf-id": intfID,
2582 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002583 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002584}
2585
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002586//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302587func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002588 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002589
2590 if packetIn.IntfType == "pon" {
2591 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002592 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002593 onuID, uniID := packetIn.OnuId, packetIn.UniId
2594 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 +00002595
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002596 if packetIn.PortNo != 0 {
2597 logicalPortNum = packetIn.PortNo
2598 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002599 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002600 }
2601 // 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 +00002602 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002603 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002604 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002605 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002606
2607 if logger.V(log.DebugLevel) {
2608 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2609 log.Fields{
2610 "logical-port-num": logicalPortNum,
2611 "intf-type": packetIn.IntfType,
2612 "packet": hex.EncodeToString(packetIn.Pkt),
2613 })
2614 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002615 return logicalPortNum, nil
2616}
2617
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002618//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002619func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002620 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002621
2622 ctag, priority, err := getCTagFromPacket(ctx, packet)
2623 if err != nil {
2624 return 0, err
2625 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302626
Esin Karaman7fb80c22020-07-16 14:23:33 +00002627 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002628 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002629 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002630 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002631 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302632 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002633 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302634 log.Fields{
2635 "pktinkey": pktInkey,
2636 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002637
2638 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002639 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302640 //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 +00002641 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302642 if err == nil {
2643 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002644 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302645 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002646 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002647 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302648 log.Fields{
2649 "pktinkey": pktInkey,
2650 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302651 return gemPortID, nil
2652 }
2653 }
Shrey Baid26912972020-04-16 21:02:31 +05302654 return uint32(0), olterrors.NewErrNotFound("gem-port",
2655 log.Fields{
2656 "pktinkey": pktInkey,
2657 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002658
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002659}
2660
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002661func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2662 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002663 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002664 classifier[PacketTagType] = DoubleTag
2665 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002666 /* We manage flowId resource pool on per PON port basis.
2667 Since this situation is tricky, as a hack, we pass the NNI port
2668 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002669 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002670 on NNI port, use onu_id as -1 (invalid)
2671 ****************** CAVEAT *******************
2672 This logic works if the NNI Port Id falls within the same valid
2673 range of PON Port Ids. If this doesn't work for some OLT Vendor
2674 we need to have a re-look at this.
2675 *********************************************
2676 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002677 onuID := -1
2678 uniID := -1
2679 gemPortID := -1
2680 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002681 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302682 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302683 return olterrors.NewErrNotFound("nni-intreface-id",
2684 log.Fields{
2685 "classifier": classifier,
2686 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002687 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302688 }
2689
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002690 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002691 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002692 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002693 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002694
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002695 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2696 log.Fields{
2697 "classifier": classifier,
2698 "action": action,
2699 "flowId": logicalFlow.Id,
2700 "intf-id": networkInterfaceID})
2701
David K. Bainbridge794735f2020-02-11 21:01:37 -08002702 classifierProto, err := makeOpenOltClassifierField(classifier)
2703 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002704 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002705 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002706 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002707 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002708 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002709 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002710 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002711 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002712 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2713 OnuId: int32(onuID), // OnuId not required
2714 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002715 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002716 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002717 AllocId: int32(allocID), // AllocId not used
2718 NetworkIntfId: int32(networkInterfaceID),
2719 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002720 Classifier: classifierProto,
2721 Action: actionProto,
2722 Priority: int32(logicalFlow.Priority),
2723 Cookie: logicalFlow.Cookie,
2724 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002725 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002726 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002727 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002728 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002729 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002730}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002731
Esin Karamanae41e2b2019-12-17 18:13:13 +00002732//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2733func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2734 var packetType string
2735 ovid, ivid := false, false
2736 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2737 vid := vlanID & VlanvIDMask
2738 if vid != ReservedVlan {
2739 ovid = true
2740 }
2741 }
2742 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2743 vid := uint32(metadata)
2744 if vid != ReservedVlan {
2745 ivid = true
2746 }
2747 }
2748 if ovid && ivid {
2749 packetType = DoubleTag
2750 } else if !ovid && !ivid {
2751 packetType = Untagged
2752 } else {
2753 packetType = SingleTag
2754 }
2755 return packetType
2756}
2757
2758//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002759func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002760 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002761 action := make(map[string]interface{})
2762 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2763 action[TrapToHost] = true
2764 /* We manage flowId resource pool on per PON port basis.
2765 Since this situation is tricky, as a hack, we pass the NNI port
2766 index (network_intf_id) as PON port Index for the flowId resource
2767 pool. Also, there is no ONU Id available for trapping packets
2768 on NNI port, use onu_id as -1 (invalid)
2769 ****************** CAVEAT *******************
2770 This logic works if the NNI Port Id falls within the same valid
2771 range of PON Port Ids. If this doesn't work for some OLT Vendor
2772 we need to have a re-look at this.
2773 *********************************************
2774 */
2775 onuID := -1
2776 uniID := -1
2777 gemPortID := -1
2778 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002779 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002780 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302781 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002782 "classifier": classifier,
2783 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002784 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002785 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002786 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002787 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002788 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002789 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002790
David K. Bainbridge794735f2020-02-11 21:01:37 -08002791 classifierProto, err := makeOpenOltClassifierField(classifier)
2792 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002793 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002794 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002795 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002796 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002797 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002798 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002799 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002800 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002801 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2802 OnuId: int32(onuID), // OnuId not required
2803 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002804 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002805 FlowType: Downstream,
2806 AllocId: int32(allocID), // AllocId not used
2807 NetworkIntfId: int32(networkInterfaceID),
2808 GemportId: int32(gemPortID), // GemportId not used
2809 Classifier: classifierProto,
2810 Action: actionProto,
2811 Priority: int32(logicalFlow.Priority),
2812 Cookie: logicalFlow.Cookie,
2813 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002814 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002815 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002816 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002817 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002818
David K. Bainbridge794735f2020-02-11 21:01:37 -08002819 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002820}
2821
salmansiddiqui7ac62132019-08-22 03:58:50 +00002822func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2823 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302824 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002825 }
2826 if Dir == tp_pb.Direction_UPSTREAM {
2827 return "upstream", nil
2828 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2829 return "downstream", nil
2830 }
2831 return "", nil
2832}
2833
Kent Hagermane6ff1012020-07-14 15:07:53 -04002834// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302835func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002836 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002837 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002838 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002839 intfID := args[IntfID]
2840 onuID := args[OnuID]
2841 uniID := args[UniID]
2842 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002843 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002844 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002845 gemToAes := make(map[uint32]bool)
2846
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002847 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002848 var direction = tp_pb.Direction_UPSTREAM
2849 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002850 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002851 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002852 attributes = TpInst.UpstreamGemPortAttributeList
2853 } else {
2854 attributes = TpInst.DownstreamGemPortAttributeList
2855 direction = tp_pb.Direction_DOWNSTREAM
2856 }
2857 default:
2858 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2859 return
2860 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002861
2862 if len(gemPorts) == 1 {
2863 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002864 gemPortID = gemPorts[0]
2865 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002866 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2867 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002868 pBitMap := attributes[idx].PbitMap
2869 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2870 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2871 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002872 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002873 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2874 if pbitSet == pbit1 {
2875 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2876 pbitToGem[pcp] = gemID
2877 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002878 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002879 }
2880 }
2881 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002882 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2883 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2884 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002885 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002886 }
2887
Gamze Abaka7650be62021-02-26 10:50:36 +00002888 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2889 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2890
salmansiddiqui7ac62132019-08-22 03:58:50 +00002891 if ipProto, ok := classifierInfo[IPProto]; ok {
2892 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002893 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002894 "tp-id": tpID,
2895 "alloc-id": allocID,
2896 "intf-id": intfID,
2897 "onu-id": onuID,
2898 "uni-id": uniID,
2899 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002900 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002901 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002902 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002903 }
2904
Girish Gowdra32625212020-04-29 11:26:35 -07002905 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002906 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302907 log.Fields{
2908 "intf-id": intfID,
2909 "onu-id": onuID,
2910 "uni-id": uniID,
2911 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002912 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002913 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002914 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002915 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002916 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002917 return
2918 }
2919 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002920 if ethType.(uint32) == EapEthType {
2921 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002922 "intf-id": intfID,
2923 "onu-id": onuID,
2924 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002925 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002926 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002927 var vlanID uint32
2928 if val, ok := classifierInfo[VlanVid]; ok {
2929 vlanID = (val.(uint32)) & VlanvIDMask
2930 } else {
2931 vlanID = DefaultMgmtVlan
2932 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002933 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002934 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002935 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002936 } else if ethType.(uint32) == PPPoEDEthType {
2937 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2938 "tp-id": tpID,
2939 "alloc-id": allocID,
2940 "intf-id": intfID,
2941 "onu-id": onuID,
2942 "uni-id": uniID,
2943 })
2944 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002945 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002946 logger.Warn(ctx, err)
2947 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002948 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002949 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002950 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002951 "intf-id": intfID,
2952 "onu-id": onuID,
2953 "uni-id": uniID,
2954 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002955 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002956 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002957 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002958 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002959 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002960 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002961 "intf-id": intfID,
2962 "onu-id": onuID,
2963 "uni-id": uniID,
2964 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002965 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002966 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002967 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002968 }
2969 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002970 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302971 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002972 "intf-id": intfID,
2973 "onu-id": onuID,
2974 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302975 "classifier": classifierInfo,
2976 "action": actionInfo,
2977 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002978 return
2979 }
2980 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002981 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002982 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002983 logger.Warn(ctx, err)
2984 }
2985 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002986}
2987
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002988func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002989 f.gemToFlowIDsKey.RLock()
2990 flowIDList := f.gemToFlowIDs[gemPortID]
2991 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002992 return len(flowIDList) > 1
2993
Gamze Abakafee36392019-10-03 11:17:24 +00002994}
2995
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002996func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpInst *tp_pb.TechProfileInstance, gemPortID uint32) (bool, uint32) {
npujarec5762e2020-01-01 14:08:48 +05302997 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002998 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2999 for _, currentGemPort := range currentGemPorts {
3000 for _, tpGemPort := range tpGemPorts {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003001 if (currentGemPort == tpGemPort.GemportId) && (currentGemPort != gemPortID) {
Gamze Abakafee36392019-10-03 11:17:24 +00003002 return true, currentGemPort
3003 }
3004 }
3005 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003006 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
3007 return false, 0
3008}
Girish Gowdra54934262019-11-13 14:19:55 +05303009
Gamze Abakacb0e6772021-06-10 08:32:12 +00003010func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003011 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
3012 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
3013 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 +00003014 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303015 for i := 0; i < len(tpInstances); i++ {
3016 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00003017 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003018 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Gamze Abakacb0e6772021-06-10 08:32:12 +00003019 logger.Debugw(ctx, "alloc-is-in-use",
3020 log.Fields{
3021 "device-id": f.deviceHandler.device.Id,
3022 "intfID": sq.intfID,
3023 "onuID": sq.onuID,
3024 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003025 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00003026 })
3027 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303028 }
3029 }
3030 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003031 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003032}
3033
Neha Sharma96b7bf22020-06-15 10:37:32 +00003034func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003035 for _, field := range flows.GetOfbFields(flow) {
3036 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003037 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003038 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003039 } else if field.Type == flows.ETH_DST {
3040 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003041 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003042 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003043 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003044 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003045 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003046 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003047 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003048 } else if field.Type == flows.VLAN_VID {
Andrea Campanellafaa42152021-10-28 11:50:56 +05303049 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3050 if field.GetVlanVid() != ReservedVlan {
3051 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3052 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3053 }
Scott Baker355d1742019-10-24 10:57:52 -07003054 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003055 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003056 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003057 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003058 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003059 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003060 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003061 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003062 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003063 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003064 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003065 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003066 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003067 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003068 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003069 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003070 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003071 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003072 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003073 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003074 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003075 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003076 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003077 return
3078 }
3079 }
3080}
3081
Neha Sharma96b7bf22020-06-15 10:37:32 +00003082func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003083 for _, action := range flows.GetActions(flow) {
3084 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003085 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003086 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003087 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003088 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003089 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003090 }
Scott Baker355d1742019-10-24 10:57:52 -07003091 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003092 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003093 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003094 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003095 if out := action.GetPush(); out != nil {
3096 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003097 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003098 } else {
3099 actionInfo[PushVlan] = true
3100 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003101 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303102 log.Fields{
3103 "push-tpid": actionInfo[TPID].(uint32),
3104 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003105 }
3106 }
Scott Baker355d1742019-10-24 10:57:52 -07003107 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003108 if out := action.GetSetField(); out != nil {
3109 if field := out.GetField(); field != nil {
3110 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003111 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003112 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003113 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3114 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003115 }
3116 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003117 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003118 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003119 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003120 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003121 }
3122 }
3123 return nil
3124}
3125
Neha Sharma96b7bf22020-06-15 10:37:32 +00003126func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003127 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003128 fieldtype := ofbField.GetType()
3129 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003130 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3131 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003132 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003133 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003134 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003135 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003136 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3137 pcp := ofbField.GetVlanPcp()
3138 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003139 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003140 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003141 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003142 }
3143 }
3144}
3145
Neha Sharma96b7bf22020-06-15 10:37:32 +00003146func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003147 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003148 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003149 } else {
3150 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003151 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003152 }
3153}
3154
Neha Sharma96b7bf22020-06-15 10:37:32 +00003155func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003156 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003157 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003158 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003159 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003160 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003161 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003162 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303163 log.Fields{
3164 "newinport": classifierInfo[InPort].(uint32),
3165 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003166 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303167 return olterrors.NewErrNotFound("child-in-port",
3168 log.Fields{
3169 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3170 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003171 }
3172 }
3173 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003174 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003175 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003176 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003177 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003178 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003179 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303180 log.Fields{
3181 "newoutport": actionInfo[Output].(uint32),
3182 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003183 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303184 return olterrors.NewErrNotFound("out-port",
3185 log.Fields{
3186 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3187 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003188 }
3189 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003190 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003191 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003192 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003193 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303194 log.Fields{
3195 "newinport": actionInfo[Output].(uint32),
3196 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003197 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303198 return olterrors.NewErrNotFound("nni-port",
3199 log.Fields{
3200 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3201 "in-port": classifierInfo[InPort].(uint32),
3202 "out-port": actionInfo[Output].(uint32),
3203 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003204 }
3205 }
3206 }
3207 return nil
3208}
Gamze Abakafee36392019-10-03 11:17:24 +00003209
Neha Sharma96b7bf22020-06-15 10:37:32 +00003210func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003211 /* Metadata 8 bytes:
3212 Most Significant 2 Bytes = Inner VLAN
3213 Next 2 Bytes = Tech Profile ID(TPID)
3214 Least Significant 4 Bytes = Port ID
3215 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3216 subscriber related flows.
3217 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003218 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003219 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003220 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003221 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003222 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003223 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003224}
3225
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003226func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3227 for _, sliceElement := range slice {
3228 if sliceElement == item {
3229 return slice
3230 }
3231 }
3232 return append(slice, item)
3233}
3234
3235func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003236 for _, sliceElement := range slice {
3237 if sliceElement == item {
3238 return slice
3239 }
3240 }
3241 return append(slice, item)
3242}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303243
3244// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003245func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303246
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003247 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303248 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003249 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003250 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003251 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003252 log.Fields{
3253 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003254 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003255 return uint32(0), err
3256 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003257 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303258 return intfID, nil
3259 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003260 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003261 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003262 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003263 log.Fields{
3264 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003265 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003266 return uint32(0), err
3267 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003268 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303269 return intfID, nil
3270 }
3271 return uint32(0), nil
3272}
3273
3274// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003275func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3276 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3277 if err != nil {
3278 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3279 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3280 return
3281 }
3282 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003283
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003284 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003285 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003286 f.packetInGemPortLock.RUnlock()
3287
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303288 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003289 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003290 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 +05303291 log.Fields{
3292 "pktinkey": pktInkey,
3293 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003294 return
3295 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303296 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003297 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003298 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003299 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003300
npujarec5762e2020-01-01 14:08:48 +05303301 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003302 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 +05303303 log.Fields{
3304 "pktinkey": pktInkey,
3305 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303306}
3307
Esin Karaman7fb80c22020-07-16 14:23:33 +00003308//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3309func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3310 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003311 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003312 return 0, 0, errors.New("invalid packet length")
3313 }
3314 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3315 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3316
3317 var index int8
3318 if outerEthType == 0x8100 {
3319 if innerEthType == 0x8100 {
3320 // q-in-q 802.1ad or 802.1q double tagged packet.
3321 // get the inner vlanId
3322 index = 18
3323 } else {
3324 index = 14
3325 }
3326 priority := (packet[index] >> 5) & 0x7
3327 //13 bits composes vlanId value
3328 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3329 return vlan, priority, nil
3330 }
3331 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3332 return 0, 0, nil
3333}
3334
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003335func (f *OpenOltFlowMgr) loadFlowIDsForGemAndGemIDsForFlow(ctx context.Context) {
3336 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - start")
3337 f.onuGemInfoLock.RLock()
3338 f.gemToFlowIDsKey.Lock()
3339 f.flowIDToGemsLock.Lock()
3340 for _, og := range f.onuGemInfoMap {
3341 for _, gem := range og.GemPorts {
3342 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, f.ponPortIdx, gem)
Gamze Abaka6f345c12021-09-08 01:14:33 +00003343 if err == nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003344 f.gemToFlowIDs[gem] = flowIDs
3345 for _, flowID := range flowIDs {
3346 if _, ok := f.flowIDToGems[flowID]; !ok {
3347 f.flowIDToGems[flowID] = []uint32{gem}
3348 } else {
3349 f.flowIDToGems[flowID] = appendUnique32bit(f.flowIDToGems[flowID], gem)
3350 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303351 }
3352 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303353 }
3354 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003355 f.flowIDToGemsLock.Unlock()
3356 f.gemToFlowIDsKey.Unlock()
3357 f.onuGemInfoLock.RUnlock()
3358 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - end")
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303359}
Esin Karamanccb714b2019-11-29 15:02:06 +00003360
Girish Gowdra9602eb42020-09-09 15:50:39 -07003361//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3362// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003363func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003364 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003365 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3366 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003367 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003368 "flow-id": flow.Id,
3369 "device-id": f.deviceHandler.device.Id})
3370 // Remove from device
3371 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3372 // DKB
3373 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3374 log.Fields{
3375 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003376 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003377 return err
3378 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003379
3380 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003381}
3382
khenaidoodc2116e2021-10-19 17:33:19 -04003383func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003384 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003385 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003386 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003387 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003388 }
3389
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003390 switch tpInst := tpInst.(type) {
3391 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003392 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003393 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003394 DeviceId: onuDeviceID,
3395 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003396 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003397 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003398 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003399 case *tp_pb.EponTechProfileInstance:
3400 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003401 DeviceId: onuDeviceID,
3402 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003403 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003404 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003405 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003406 default:
3407 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003408 }
khenaidoodc2116e2021-10-19 17:33:19 -04003409 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003410 DeviceId: onuDeviceID,
3411 UniId: uniID,
3412 TpInstancePath: tpPath,
3413 TechTpInstance: nil,
3414 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003415}
3416
Girish Gowdrabcf98af2021-07-01 08:24:42 -07003417func (f *OpenOltFlowMgr) getOnuGemInfoList(ctx context.Context) []rsrcMgr.OnuGemInfo {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003418 var onuGemInfoLst []rsrcMgr.OnuGemInfo
3419 f.onuGemInfoLock.RLock()
3420 defer f.onuGemInfoLock.RUnlock()
3421 for _, v := range f.onuGemInfoMap {
3422 onuGemInfoLst = append(onuGemInfoLst, *v)
3423 }
3424 return onuGemInfoLst
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003425}