blob: 3f09ba41701d698b21f354e7d6905f028a13246d [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 */
Gamze Abaka6d0a64f2021-11-18 08:08:33 +0000387 return f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530388}
389
salmansiddiqui7ac62132019-08-22 03:58:50 +0000390// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530391func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400392
Neha Sharma96b7bf22020-06-15 10:37:32 +0000393 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530394 log.Fields{"dir": sq.direction,
395 "intf-id": sq.intfID,
396 "onu-id": sq.onuID,
397 "uni-id": sq.uniID,
398 "tp-id": sq.tpID,
399 "meter-id": sq.meterID,
400 "tp-inst": sq.tpInst,
401 "flowmetadata": sq.flowMetadata,
402 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400403
Gamze Abakafee36392019-10-03 11:17:24 +0000404 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000405 if err != nil {
406 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400407 }
408
409 /* Lets make a simple assumption that if the meter-id is present on the KV store,
410 * then the scheduler and queues configuration is applied on the OLT device
411 * in the given direction.
412 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000413
Manikkaraj kb1d51442019-07-23 10:41:02 -0400414 var SchedCfg *tp_pb.SchedulerConfig
Girish Gowdraa482f272021-03-24 23:04:19 -0700415 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400416 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530417 return olterrors.NewErrNotFound("meter",
418 log.Fields{"intf-id": sq.intfID,
419 "onu-id": sq.onuID,
420 "uni-id": sq.uniID,
421 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400422 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000423
Girish Gowdraa482f272021-03-24 23:04:19 -0700424 if meterInfo != nil {
425 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 -0700426 if meterInfo.MeterID == sq.meterID {
Girish Gowdraa482f272021-03-24 23:04:19 -0700427 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
428 return err
429 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400430 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400431 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530432 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800433 "unsupported": "meter-id",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700434 "kv-store-meter-id": meterInfo.MeterID,
Shrey Baid26912972020-04-16 21:02:31 +0530435 "meter-id-in-flow": sq.meterID,
436 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400437 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000438
Neha Sharma96b7bf22020-06-15 10:37:32 +0000439 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530440 log.Fields{
441 "meter-id": sq.meterID,
442 "direction": Direction,
443 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000444
Gamze Abakafee36392019-10-03 11:17:24 +0000445 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700446 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Gamze Abakafee36392019-10-03 11:17:24 +0000447 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700448 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Girish Kumar8f73fe02019-12-09 13:19:37 +0000449 }
450
Girish Gowdraa482f272021-03-24 23:04:19 -0700451 found := false
452 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000453 if sq.flowMetadata != nil {
454 for _, meter := range sq.flowMetadata.Meters {
455 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700456 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700457 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 +0000458 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700459 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530460 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700461 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400462 break
463 }
464 }
465 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000466 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400467 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700468 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530469 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800470 "reason": "Could-not-get-meterbands-from-flowMetadata",
471 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530472 "meter-id": sq.meterID,
473 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400474 }
Gamze Abaka01174422021-03-10 06:55:27 +0000475
476 var TrafficShaping *tp_pb.TrafficShapingInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700477 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
Gamze Abaka01174422021-03-10 06:55:27 +0000478 return olterrors.NewErrInvalidValue(log.Fields{
479 "reason": "invalid-meter-config",
480 "meter-id": sq.meterID,
481 "device-id": f.deviceHandler.device.Id}, nil)
482 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400483
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700484 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000485 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400486
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700487 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530488 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
489 log.Fields{"intf-id": sq.intfID,
490 "direction": sq.direction,
491 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400492 }
493
salmansiddiqui7ac62132019-08-22 03:58:50 +0000494 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400495 * store the meter id on the KV store, for further reference.
496 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700497 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 +0530498 return olterrors.NewErrAdapter("failed-updating-meter-id",
499 log.Fields{"onu-id": sq.onuID,
500 "meter-id": sq.meterID,
501 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400502 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000503 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530504 log.Fields{"direction": Direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700505 "meter-info": meterInfo,
506 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400507 return nil
508}
509
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700510func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700511 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000512
513 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530514 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
515 log.Fields{"intf-id": sq.intfID,
516 "direction": sq.direction,
517 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000518 }
519
Gamze Abakacb0e6772021-06-10 08:32:12 +0000520 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
521 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
522 log.Fields{
523 "direction": sq.direction,
524 "TrafficScheds": TrafficSched,
525 "device-id": f.deviceHandler.device.Id,
526 "intfID": sq.intfID,
527 "onuID": sq.onuID,
528 "uniID": sq.uniID})
529 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
530 IntfId: sq.intfID, OnuId: sq.onuID,
531 UniId: sq.uniID, PortNo: sq.uniPort,
532 TrafficScheds: TrafficSched}); err != nil {
533 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
534 }
535 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
536 "direction": sq.direction,
537 "traffic-queues": trafficQueues,
538 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000539 }
540
541 // On receiving the CreateTrafficQueues request, the driver should create corresponding
542 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000543 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530544 log.Fields{"direction": sq.direction,
545 "traffic-queues": trafficQueues,
546 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530547 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000548 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
549 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000550 TrafficQueues: trafficQueues,
551 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530552 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000553 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000554 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530555 "direction": sq.direction,
556 "traffic-queues": trafficQueues,
557 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000558
Esin Karamanccb714b2019-11-29 15:02:06 +0000559 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700560 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000561 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700562 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 +0000563 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
564 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000565 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000566 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700567 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000568 gemPortID: multicastQueuePerPonPort.GemportId,
569 servicePriority: multicastQueuePerPonPort.Priority,
570 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700571 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000572 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400573 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700574 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400575 return err
576 }
Shrey Baid26912972020-04-16 21:02:31 +0530577
Neha Sharma96b7bf22020-06-15 10:37:32 +0000578 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000579 }
580 }
581 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000582 return nil
583}
584
salmansiddiqui7ac62132019-08-22 03:58:50 +0000585// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530586func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400587
588 var Direction string
589 var SchedCfg *tp_pb.SchedulerConfig
590 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000591 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530592 log.Fields{
593 "direction": sq.direction,
594 "intf-id": sq.intfID,
595 "onu-id": sq.onuID,
596 "uni-id": sq.uniID,
597 "uni-port": sq.uniPort,
598 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000599 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700600 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400601 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000602 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700603 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400604 Direction = "downstream"
605 }
606
Girish Gowdraa482f272021-03-24 23:04:19 -0700607 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 -0400608
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700609 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000610 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000611
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700612 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000613 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530614 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
615 log.Fields{
616 "intf-id": sq.intfID,
617 "direction": sq.direction,
618 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000619 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400620
npujarec5762e2020-01-01 14:08:48 +0530621 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000622 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
623 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000624 TrafficQueues: TrafficQueues,
625 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000626 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530627 log.Fields{
628 "intf-id": sq.intfID,
629 "traffic-queues": TrafficQueues,
630 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400631 }
Gamze Abakacb0e6772021-06-10 08:32:12 +0000632 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400633
Gamze Abakacb0e6772021-06-10 08:32:12 +0000634 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
635 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
636 IntfId: sq.intfID, OnuId: sq.onuID,
637 UniId: sq.uniID, PortNo: sq.uniPort,
638 TrafficScheds: TrafficSched}); err != nil {
639 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
640 log.Fields{
641 "intf-id": sq.intfID,
642 "traffic-schedulers": TrafficSched,
643 "onu-id": sq.onuID,
644 "uni-id": sq.uniID,
645 "uni-port": sq.uniPort}, err)
646 }
647
648 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
649 log.Fields{"device-id": f.deviceHandler.device.Id,
650 "intf-id": sq.intfID,
651 "onu-id": sq.onuID,
652 "uni-id": sq.uniID,
653 "uni-port": sq.uniPort})
654
655 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700656 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
Gamze Abakacb0e6772021-06-10 08:32:12 +0000657 f.resourceMgr.FreeAllocID(ctx, sq.intfID, sq.onuID, sq.uniID, allocID)
658 // Delete the TCONT on the ONU.
659 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
660 tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
661 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
662 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
663 log.Fields{
664 "intf": sq.intfID,
665 "onu-id": sq.onuID,
666 "uni-id": sq.uniID,
667 "device-id": f.deviceHandler.device.Id,
668 "alloc-id": allocID})
669 }
670 }
671 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000672
673 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400674 * delete the meter id on the KV store.
675 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700676 err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400677 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530678 return olterrors.NewErrAdapter("unable-to-remove-meter",
679 log.Fields{
680 "onu": sq.onuID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700681 "device-id": f.deviceHandler.device.Id,
682 "intf-id": sq.intfID,
683 "onu-id": sq.onuID,
684 "uni-id": sq.uniID,
685 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400686 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000687 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530688 log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530689 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700690 "device-id": f.deviceHandler.device.Id,
691 "intf-id": sq.intfID,
692 "onu-id": sq.onuID,
693 "uni-id": sq.uniID,
694 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400695 return err
696}
697
Girish Gowdra197acc12021-08-16 10:59:45 -0700698// We are trying to force remove the schedulers and queues here if one exists for the given key.
699// We ignore any errors encountered in the process. The errors most likely are encountered when
700// the schedulers and queues are already cleared for the given key.
701func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
702
703 var schedCfg *tp_pb.SchedulerConfig
704 var err error
705 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
706 log.Fields{
707 "direction": sq.direction,
708 "intf-id": sq.intfID,
709 "onu-id": sq.onuID,
710 "uni-id": sq.uniID,
711 "uni-port": sq.uniPort,
712 "tp-id": sq.tpID,
713 "device-id": f.deviceHandler.device.Id})
714 if sq.direction == tp_pb.Direction_UPSTREAM {
715 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
716 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
717 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
718 }
719
720 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
721 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
722 TrafficSched[0].TechProfileId = sq.tpID
723
724 // Remove traffic queues. Ignore any errors, just log them.
725 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
726 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
727 "direction": sq.direction,
728 "intf-id": sq.intfID,
729 "onu-id": sq.onuID,
730 "uni-id": sq.uniID,
731 "uni-port": sq.uniPort,
732 "tp-id": sq.tpID,
733 "device-id": f.deviceHandler.device.Id,
734 "err": err})
735 } else {
736 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
737 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
738 UniId: sq.uniID, PortNo: sq.uniPort,
739 TrafficQueues: TrafficQueues,
740 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
741 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
742 "direction": sq.direction,
743 "intf-id": sq.intfID,
744 "onu-id": sq.onuID,
745 "uni-id": sq.uniID,
746 "uni-port": sq.uniPort,
747 "tp-id": sq.tpID,
748 "device-id": f.deviceHandler.device.Id,
749 "err": err})
750
751 } else {
752 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
753 "direction": sq.direction,
754 "intf-id": sq.intfID,
755 "onu-id": sq.onuID,
756 "uni-id": sq.uniID,
757 "uni-port": sq.uniPort,
758 "tp-id": sq.tpID})
759 }
760 }
761
762 // Remove traffic schedulers. Ignore any errors, just log them.
763 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
764 IntfId: sq.intfID, OnuId: sq.onuID,
765 UniId: sq.uniID, PortNo: sq.uniPort,
766 TrafficScheds: TrafficSched}); err != nil {
767 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
768 "direction": sq.direction,
769 "intf-id": sq.intfID,
770 "onu-id": sq.onuID,
771 "uni-id": sq.uniID,
772 "uni-port": sq.uniPort,
773 "tp-id": sq.tpID,
774 "device-id": f.deviceHandler.device.Id,
775 "err": err})
776 } else {
777 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
778 "direction": sq.direction,
779 "intf-id": sq.intfID,
780 "onu-id": sq.onuID,
781 "uni-id": sq.uniID,
782 "uni-port": sq.uniPort,
783 "tp-id": sq.tpID})
784 }
785}
786
Gamze Abakafee36392019-10-03 11:17:24 +0000787// This function allocates tconts and GEM ports for an ONU
khenaidoodc2116e2021-10-19 17:33:19 -0400788func (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 +0000789 var allocIDs []uint32
790 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530791 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530792 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000793 var err error
npujarec5762e2020-01-01 14:08:48 +0530794 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
795 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000796 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530797
Neha Sharma96b7bf22020-06-15 10:37:32 +0000798 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530799 "intf-id": intfID,
800 "onu-id": onuID,
801 "uni-id": uniID,
802 "device-id": f.deviceHandler.device.Id,
803 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530804
Manikkaraj kb1d51442019-07-23 10:41:02 -0400805 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700806 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000807 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000808 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530809 log.Fields{
810 "path": tpPath,
811 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700812 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000813 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530814 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000815 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530816 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700817 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530818 "tp-id": TpID,
819 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000820 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530821 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400822 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700823 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400824 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530825 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000826 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530827 log.Fields{
828 "uni": uni,
829 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530830 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530831 }
Gamze Abakafee36392019-10-03 11:17:24 +0000832
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700833 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700834 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700835 if UsMeterID != 0 {
836 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
837 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
838 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000839 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700840 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700841 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700842 "onu-id": onuID,
843 "uni-id": uniID,
844 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700845 "meter-id": UsMeterID,
846 "device-id": f.deviceHandler.device.Id})
847 return 0, nil, nil
848 }
849 }
850 if DsMeterID != 0 {
851 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
852 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
853 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000854 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700855 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700856 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700857 "onu-id": onuID,
858 "uni-id": uniID,
859 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700860 "meter-id": DsMeterID,
861 "device-id": f.deviceHandler.device.Id})
862 return 0, nil, nil
863 }
864 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700865 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700866 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700867 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700868 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700869 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000870
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700871 if tpInstanceExists {
872 return allocID, gemPortIDs, techProfileInstance
873 }
874
875 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700876 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700877 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000878 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700879 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700880 "intf-id": intfID,
881 "onu-id": onuID,
882 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700883 "alloc-ids": allocIDs,
884 "gemports": allgemPortIDs,
885 "device-id": f.deviceHandler.device.Id})
886 // Send Tconts and GEM ports to KV store
887 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530888 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400889 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700890 // CreateSchedulerQueues for EPON needs to be implemented here
891 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700892 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700893 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700894 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700895 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700896 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700897
898 if tpInstanceExists {
899 return allocID, gemPortIDs, techProfileInstance
900 }
901
902 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700903 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700904 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000905 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700906 log.Fields{
907 "alloc-ids": allocIDs,
908 "gemports": allgemPortIDs,
909 "device-id": f.deviceHandler.device.Id})
910 // Send Tconts and GEM ports to KV store
911 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
912 return allocID, gemPortIDs, techProfileInstance
913 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000914 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700915 log.Fields{
916 "tpInst": tpInst})
917 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530918 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530919}
920
npujarec5762e2020-01-01 14:08:48 +0530921func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530922
Neha Sharma96b7bf22020-06-15 10:37:32 +0000923 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530924 log.Fields{
925 "intf-id": intfID,
926 "onu-id": onuID,
927 "uni-id": uniID,
928 "alloc-id": allocID,
929 "gemport-ids": gemPortIDs,
930 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530931 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530932 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000933 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 +0530934 }
npujarec5762e2020-01-01 14:08:48 +0530935 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000936 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 +0530937 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700938
Neha Sharma96b7bf22020-06-15 10:37:32 +0000939 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 -0400940 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530941 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400942 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530943}
944
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700945func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530946 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000947 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700948 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
949 var err error
950 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
951 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
952 if err != nil || f.techprofile == nil {
953 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
954 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
955 }
956 logger.Debugw(ctx, "init-tech-profile-done",
957 log.Fields{
958 "intf-id": intfID,
959 "device-id": f.deviceHandler.device.Id})
960 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700961 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530962 }
963 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700964 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
965 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 +0530966}
967
Gamze Abaka7650be62021-02-26 10:50:36 +0000968func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Andrea Campanellafaa42152021-10-28 11:50:56 +0530969 flowContext.classifier[PacketTagType] = SingleTag // FIXME: This hardcoding needs to be removed.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000970 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530971 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000972 "uplinkClassifier": flowContext.classifier,
973 "uplinkAction": flowContext.action})
974 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530975 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530976}
977
Gamze Abaka7650be62021-02-26 10:50:36 +0000978func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
979 downlinkClassifier := flowContext.classifier
980 downlinkAction := flowContext.action
981
Andrea Campanellafaa42152021-10-28 11:50:56 +0530982 // TODO: For now mark the PacketTagType as SingleTag when OLT is transparent to VLAN
983 // Per some deployment models, it is also possible that ONU operates on double tagged packets,
984 // so this hardcoding of SingeTag packet-tag-type may be problem for such deployment models.
985 // Need a better way for detection of packet tag type from OpenFlow message.
986 if _, ok := downlinkClassifier[VlanVid]; !ok {
987 downlinkClassifier[PacketTagType] = SingleTag
988 } else {
989 downlinkClassifier[PacketTagType] = DoubleTag
990 downlinkAction[PopVlan] = true
991 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000992 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530993 log.Fields{
994 "downlinkClassifier": downlinkClassifier,
995 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400996 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
997 if vlan, exists := downlinkClassifier[VlanVid]; exists {
998 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700999 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001000 if uint32(metadata.(uint64)) == plt.MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001001 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301002 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001003 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301004 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +00001005 "onu-id": flowContext.onuID,
1006 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001007 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -04001008 }
1009 }
1010 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301011 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001012
Matt Jeannereted16b7c2019-11-01 13:31:35 -04001013 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1014 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +05301015 if ok {
1016 downlinkAction[VlanVid] = dlClVid & 0xfff
Girish Gowdra26f344b2019-10-23 14:39:13 +05301017 }
1018
Gamze Abaka7650be62021-02-26 10:50:36 +00001019 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301020}
1021
Gamze Abaka7650be62021-02-26 10:50:36 +00001022func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001023
Gamze Abaka7650be62021-02-26 10:50:36 +00001024 intfID := flowContext.intfID
1025 onuID := flowContext.onuID
1026 uniID := flowContext.uniID
1027 classifier := flowContext.classifier
1028 action := flowContext.action
1029 allocID := flowContext.allocID
1030 gemPortID := flowContext.gemPortID
1031 tpID := flowContext.tpID
1032 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001033 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301034 log.Fields{
1035 "intf-id": intfID,
1036 "onu-id": onuID,
1037 "uni-id": uniID,
1038 "device-id": f.deviceHandler.device.Id,
1039 "classifier": classifier,
1040 "action": action,
1041 "direction": direction,
1042 "alloc-id": allocID,
1043 "gemport-id": gemPortID,
1044 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001045
1046 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001047 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301048 log.Fields{
1049 "device-id": f.deviceHandler.device.Id,
1050 "intf-id": intfID,
1051 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001052 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301053 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001054 classifierProto, err := makeOpenOltClassifierField(classifier)
1055 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301056 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301057 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001058 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301059 log.Fields{
1060 "classifier": *classifierProto,
1061 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001062 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001063 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301064 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301065 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001066 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301067 log.Fields{
1068 "action": *actionProto,
1069 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001070 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301071 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301072 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001073 log.Fields{
1074 "classifier": classifier,
1075 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301076 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001077 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301078 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001079
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001080 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001081 OnuId: int32(onuID),
1082 UniId: int32(uniID),
1083 FlowId: logicalFlow.Id,
1084 FlowType: direction,
1085 AllocId: int32(allocID),
1086 NetworkIntfId: int32(networkIntfID),
1087 GemportId: int32(gemPortID),
1088 Classifier: classifierProto,
1089 Action: actionProto,
1090 Priority: int32(logicalFlow.Priority),
1091 Cookie: logicalFlow.Cookie,
1092 PortNo: flowContext.portNo,
1093 TechProfileId: tpID,
1094 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1095 PbitToGemport: flowContext.pbitToGem,
1096 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001097 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001098 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001099 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301100 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001101 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301102 log.Fields{"direction": direction,
1103 "device-id": f.deviceHandler.device.Id,
1104 "flow": flow,
1105 "intf-id": intfID,
1106 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001107
David K. Bainbridge794735f2020-02-11 21:01:37 -08001108 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301109}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001110
Gamze Abaka7650be62021-02-26 10:50:36 +00001111func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1112
1113 intfID := flowContext.intfID
1114 onuID := flowContext.onuID
1115 uniID := flowContext.uniID
1116 logicalFlow := flowContext.logicalFlow
1117 classifier := flowContext.classifier
1118 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301119
Neha Sharma96b7bf22020-06-15 10:37:32 +00001120 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301121 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301122 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001123 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301124 "action": action,
1125 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001126 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301127 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301128
1129 // Clear the action map
1130 for k := range action {
1131 delete(action, k)
1132 }
1133
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001134 action[TrapToHost] = true
1135 classifier[UDPSrc] = uint32(68)
1136 classifier[UDPDst] = uint32(67)
1137 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301138
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001139 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001140 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301141 log.Fields{
1142 "device-id": f.deviceHandler.device.Id,
1143 "intf-id": intfID,
1144 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001145 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301146 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301147
Neha Sharma96b7bf22020-06-15 10:37:32 +00001148 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301149 log.Fields{
1150 "ul_classifier": classifier,
1151 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001152 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301153 "intf-id": intfID,
1154 "onu-id": onuID,
1155 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301156
David K. Bainbridge794735f2020-02-11 21:01:37 -08001157 classifierProto, err := makeOpenOltClassifierField(classifier)
1158 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301159 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301160 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001161 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001162 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001163 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301164 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301165 }
1166
David K. Bainbridge794735f2020-02-11 21:01:37 -08001167 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001168 OnuId: int32(onuID),
1169 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001170 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001171 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001172 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001173 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001174 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301175 Classifier: classifierProto,
1176 Action: actionProto,
1177 Priority: int32(logicalFlow.Priority),
1178 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001179 PortNo: flowContext.portNo,
1180 TechProfileId: flowContext.tpID,
1181 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1182 PbitToGemport: flowContext.pbitToGem,
1183 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001184 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001185 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001186 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001187 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001188 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301189 log.Fields{
1190 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001191 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301192 "intf-id": intfID,
1193 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301194
David K. Bainbridge794735f2020-02-11 21:01:37 -08001195 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301196}
1197
Esin Karamanae41e2b2019-12-17 18:13:13 +00001198//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001199func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1200 delete(flowContext.classifier, VlanVid)
1201 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001202}
1203
1204//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001205func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1206
1207 intfID := flowContext.intfID
1208 onuID := flowContext.onuID
1209 uniID := flowContext.uniID
1210 logicalFlow := flowContext.logicalFlow
1211 classifier := flowContext.classifier
1212 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001213
Neha Sharma96b7bf22020-06-15 10:37:32 +00001214 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001215 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301216 return olterrors.NewErrNotFound("nni-interface-id",
1217 log.Fields{
1218 "classifier": classifier,
1219 "action": action,
1220 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001221 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001222 }
1223
1224 // Clear the action map
1225 for k := range action {
1226 delete(action, k)
1227 }
1228
1229 action[TrapToHost] = true
1230 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001231
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001232 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001233 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001234 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001235 }
1236
Neha Sharma96b7bf22020-06-15 10:37:32 +00001237 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301238 log.Fields{
1239 "ul_classifier": classifier,
1240 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001241 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301242 "device-id": f.deviceHandler.device.Id,
1243 "intf-id": intfID,
1244 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001245
David K. Bainbridge794735f2020-02-11 21:01:37 -08001246 classifierProto, err := makeOpenOltClassifierField(classifier)
1247 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301248 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001249 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001250 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301251 log.Fields{
1252 "classifier": *classifierProto,
1253 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001254 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001255 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301256 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001257 }
1258
David K. Bainbridge794735f2020-02-11 21:01:37 -08001259 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001260 OnuId: int32(onuID),
1261 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001262 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001263 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001264 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001265 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001266 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001267 Classifier: classifierProto,
1268 Action: actionProto,
1269 Priority: int32(logicalFlow.Priority),
1270 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001271 PortNo: flowContext.portNo,
1272 TechProfileId: flowContext.tpID,
1273 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1274 PbitToGemport: flowContext.pbitToGem,
1275 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001276 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001277
David K. Bainbridge794735f2020-02-11 21:01:37 -08001278 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001279 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 -08001280 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001281
David K. Bainbridge794735f2020-02-11 21:01:37 -08001282 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001283}
1284
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001285// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001286func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1287 intfID := flowContext.intfID
1288 onuID := flowContext.onuID
1289 uniID := flowContext.uniID
1290 portNo := flowContext.portNo
1291 allocID := flowContext.allocID
1292 gemPortID := flowContext.gemPortID
1293 logicalFlow := flowContext.logicalFlow
1294 classifier := flowContext.classifier
1295 action := flowContext.action
1296
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001297 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301298 log.Fields{
1299 "intf-id": intfID,
1300 "onu-id": onuID,
1301 "port-no": portNo,
1302 "alloc-id": allocID,
1303 "gemport-id": gemPortID,
1304 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001305 "flow": logicalFlow,
1306 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301307
1308 uplinkClassifier := make(map[string]interface{})
1309 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301310
manikkaraj kbf256be2019-03-25 00:13:48 +05301311 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001312 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001313 uplinkClassifier[PacketTagType] = SingleTag
1314 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001315 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301316 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001317 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001318 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001319 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301320 "device-id": f.deviceHandler.device.Id,
1321 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001322 "intf-id": intfID,
1323 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001324 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301325 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001326 //Add Uplink EthType Flow
1327 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301328 log.Fields{
1329 "ul_classifier": uplinkClassifier,
1330 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001331 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301332 "device-id": f.deviceHandler.device.Id,
1333 "intf-id": intfID,
1334 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301335
David K. Bainbridge794735f2020-02-11 21:01:37 -08001336 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1337 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301338 return olterrors.NewErrInvalidValue(log.Fields{
1339 "classifier": uplinkClassifier,
1340 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301341 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001342 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301343 log.Fields{
1344 "classifier": *classifierProto,
1345 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001346 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001347 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301348 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301349 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001350 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301351 log.Fields{
1352 "action": *actionProto,
1353 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001354 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301355 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301356 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001357 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301358 "action": action,
1359 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001360 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301361 }
1362
David K. Bainbridge794735f2020-02-11 21:01:37 -08001363 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001364 OnuId: int32(onuID),
1365 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001366 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001367 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001368 AllocId: int32(allocID),
1369 NetworkIntfId: int32(networkIntfID),
1370 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301371 Classifier: classifierProto,
1372 Action: actionProto,
1373 Priority: int32(logicalFlow.Priority),
1374 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001375 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001376 TechProfileId: flowContext.tpID,
1377 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1378 PbitToGemport: flowContext.pbitToGem,
1379 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001380 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001381 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001382 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001383 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001384 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301385 log.Fields{
1386 "device-id": f.deviceHandler.device.Id,
1387 "onu-id": onuID,
1388 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001389 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301390 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001391
David K. Bainbridge794735f2020-02-11 21:01:37 -08001392 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301393}
1394
David K. Bainbridge794735f2020-02-11 21:01:37 -08001395func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001396 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001397
1398 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1399 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1400 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001401 if vlanID != ReservedVlan {
1402 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001403 classifier.OVid = vid
1404 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301405 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301406 // 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 -07001407 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1408 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301409 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1410 // If OLT is using transparent tag mechanism, then it classifies whatever tag it sees to/from ONU which
1411 //is OVid from the perspective of the OLT. When OLT also places or pops the outer tag, then classifierInfo[Metadata]
1412 // becomes the IVid.
1413 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1414 if vid != ReservedVlan {
1415 classifier.IVid = vid
1416 }
1417 } else {
1418 if vid != ReservedVlan {
1419 classifier.OVid = vid
1420 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001421 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301422 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301423 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001424 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301425 classifier.OPbits = vlanPcp
1426 } else {
1427 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301428 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001429 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1430 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1431 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1432 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001433 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001434 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1435 classifier.PktTagType = pktTagType
1436
1437 switch pktTagType {
1438 case SingleTag:
1439 case DoubleTag:
1440 case Untagged:
1441 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001442 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301443 }
1444 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001445 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301446}
1447
Gamze Abaka724d0852020-03-18 12:10:24 +00001448func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001449 var actionCmd openoltpb2.ActionCmd
1450 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301451 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001452 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301453 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001454 if _, ok := actionInfo[VlanPcp]; ok {
1455 action.Cmd.RemarkInnerPbits = true
1456 action.IPbits = actionInfo[VlanPcp].(uint32)
1457 if _, ok := actionInfo[VlanVid]; ok {
1458 action.Cmd.TranslateInnerTag = true
1459 action.IVid = actionInfo[VlanVid].(uint32)
1460 }
1461 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001462 } else if _, ok := actionInfo[PushVlan]; ok {
1463 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301464 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001465 if _, ok := actionInfo[VlanPcp]; ok {
1466 action.OPbits = actionInfo[VlanPcp].(uint32)
1467 action.Cmd.RemarkOuterPbits = true
1468 if _, ok := classifierInfo[VlanVid]; ok {
1469 action.IVid = classifierInfo[VlanVid].(uint32)
1470 action.Cmd.TranslateInnerTag = true
1471 }
1472 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001473 } else if _, ok := actionInfo[TrapToHost]; ok {
1474 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301475 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301476 // When OLT is transparent to vlans no-action is valid.
1477 /*
1478 else {
1479 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1480 }
1481 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001482 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301483}
1484
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001485// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001486func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001487 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301488}
1489
Gamze Abakafee36392019-10-03 11:17:24 +00001490// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001491// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1492// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1493// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1494// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1495// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1496// because it was observed that if the ONU device was deleted too soon after the flows were
1497// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1498// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1499// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001500func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301501 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001502 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1503
Gamze Abakafee36392019-10-03 11:17:24 +00001504 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001505
1506 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001507 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001508 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1509 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
1510 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1511 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1512 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1513 log.Fields{
1514 "tp-id": tpID,
1515 "path": tpPath})
1516 }
1517 switch tpInstance := tpInst.(type) {
1518 case *tp_pb.TechProfileInstance:
1519 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1520 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1521 }
1522 // Force cleanup scheduler/queues -- end
1523
1524 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301525 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001526 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301527 // return err
1528 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001529 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001530 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 +00001531 }
1532 return nil
1533}
1534
1535// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301536func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001537 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001538 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001539 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001540 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301541 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1542 log.Fields{
1543 "tp-id": tpID,
1544 "uni-port-name": uniPortName,
1545 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001546 }
1547 return nil
1548}
1549
David K. Bainbridge794735f2020-02-11 21:01:37 -08001550func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001551
1552 var intfID uint32
1553 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1554 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1555 */
1556 if deviceFlow.AccessIntfId != -1 {
1557 intfID = uint32(deviceFlow.AccessIntfId)
1558 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001559 // We need to log the valid interface ID.
1560 // 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 +00001561 intfID = uint32(deviceFlow.NetworkIntfId)
1562 }
1563
Neha Sharma96b7bf22020-06-15 10:37:32 +00001564 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301565 "flow": *deviceFlow,
1566 "device-id": f.deviceHandler.device.Id,
1567 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001568 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001569
1570 st, _ := status.FromError(err)
1571 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001572 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001573 "err": err,
1574 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301575 "device-id": f.deviceHandler.device.Id,
1576 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001577 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301578 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001579
1580 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001581 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301582 log.Fields{"err": err,
1583 "device-flow": deviceFlow,
1584 "device-id": f.deviceHandler.device.Id,
1585 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001586 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001587 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001588 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301589 log.Fields{
1590 "flow": *deviceFlow,
1591 "device-id": f.deviceHandler.device.Id,
1592 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001593
1594 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1595 if deviceFlow.AccessIntfId != -1 {
1596 // No need to register the flow if it is a trap on nni flow.
1597 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1598 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1599 return err
1600 }
1601 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001602 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001603}
1604
Neha Sharma96b7bf22020-06-15 10:37:32 +00001605func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1606 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301607 log.Fields{
1608 "flow": *deviceFlow,
1609 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001610 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001611 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001612 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001613 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301614 log.Fields{
1615 "err": err,
1616 "deviceFlow": deviceFlow,
1617 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001618 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001619 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001620 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001621 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001622
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001623 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001624 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001625 "of-flow-id": ofFlowID,
1626 "flow": *deviceFlow,
1627 "device-id": f.deviceHandler.device.Id,
1628 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001629 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301630}
1631
David K. Bainbridge794735f2020-02-11 21:01:37 -08001632func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001633
1634 classifierInfo := make(map[string]interface{})
1635 actionInfo := make(map[string]interface{})
1636
1637 classifierInfo[EthType] = uint32(LldpEthType)
1638 classifierInfo[PacketTagType] = Untagged
1639 actionInfo[TrapToHost] = true
1640
1641 // LLDP flow is installed to trap LLDP packets on the NNI port.
1642 // We manage flow_id resource pool on per PON port basis.
1643 // Since this situation is tricky, as a hack, we pass the NNI port
1644 // index (network_intf_id) as PON port Index for the flow_id resource
1645 // pool. Also, there is no ONU Id available for trapping LLDP packets
1646 // on NNI port, use onu_id as -1 (invalid)
1647 // ****************** CAVEAT *******************
1648 // This logic works if the NNI Port Id falls within the same valid
1649 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1650 // we need to have a re-look at this.
1651 // *********************************************
1652
1653 var onuID = -1
1654 var uniID = -1
1655 var gemPortID = -1
1656
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001657 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001658 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301659 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001660 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001661 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001662 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001663 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001664 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001665
David K. Bainbridge794735f2020-02-11 21:01:37 -08001666 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1667 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301668 return olterrors.NewErrInvalidValue(
1669 log.Fields{
1670 "classifier": classifierInfo,
1671 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001672 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001673 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301674 log.Fields{
1675 "classifier": *classifierProto,
1676 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001677 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001678 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301679 return olterrors.NewErrInvalidValue(
1680 log.Fields{
1681 "action": actionInfo,
1682 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001683 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001684 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301685 log.Fields{
1686 "action": *actionProto,
1687 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001688
1689 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1690 OnuId: int32(onuID), // OnuId not required
1691 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001692 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001693 FlowType: Downstream,
1694 NetworkIntfId: int32(networkInterfaceID),
1695 GemportId: int32(gemPortID),
1696 Classifier: classifierProto,
1697 Action: actionProto,
1698 Priority: int32(flow.Priority),
1699 Cookie: flow.Cookie,
1700 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001701 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001702 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301703 log.Fields{
1704 "flow": downstreamflow,
1705 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001706 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001707 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301708 log.Fields{
1709 "device-id": f.deviceHandler.device.Id,
1710 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001711 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001712
David K. Bainbridge794735f2020-02-11 21:01:37 -08001713 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301714}
1715
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001716func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1717 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001718}
1719
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001720//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001721func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001722 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1723 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1724 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001725 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301726 log.Fields{
1727 "intf-id": intfID,
1728 "onu-id": onuID,
1729 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001730 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001731 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301732 return nil, olterrors.NewErrNotFound("onu-child-device",
1733 log.Fields{
1734 "onu-id": onuID,
1735 "intf-id": intfID,
1736 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001737 }
khenaidoo106c61a2021-08-11 18:05:46 -04001738 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 -07001739 //better to ad the device to cache here.
1740 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1741 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001742 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301743 log.Fields{
1744 "intf-id": intfID,
1745 "onu-id": onuID,
1746 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001747 }
1748
1749 return onuDev.(*OnuDevice), nil
1750}
1751
1752//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001753func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1754 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301755 log.Fields{
1756 "pon-port": intfID,
1757 "onu-id": onuID,
1758 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001759 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001760 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001761 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301762 return nil, olterrors.NewErrNotFound("onu",
1763 log.Fields{
1764 "interface-id": parentPortNo,
1765 "onu-id": onuID,
1766 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001767 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301768 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001769 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301770 log.Fields{
1771 "device-id": f.deviceHandler.device.Id,
1772 "child_device_id": onuDevice.Id,
1773 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301774 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301775}
1776
Neha Sharma96b7bf22020-06-15 10:37:32 +00001777func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1778 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301779 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001780 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301781 log.Fields{
1782 "intf-id": intfID,
1783 "onu-id": onuID,
1784 "uni-id": uniID,
1785 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001786 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301787 }
1788
khenaidoodc2116e2021-10-19 17:33:19 -04001789 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001790 DeviceId: onuDev.deviceID,
1791 UniId: uniID,
1792 TpInstancePath: tpPath,
1793 GemPortId: gemPortID,
1794 }
1795 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1796
1797 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301798 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1799 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001800 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1801 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301802 "onu-id": onuDev.deviceID,
1803 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001804 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301805 }
khenaidoo106c61a2021-08-11 18:05:46 -04001806
Neha Sharma96b7bf22020-06-15 10:37:32 +00001807 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301808 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001809 "msg": delGemPortMsg,
1810 "from-adapter": f.deviceHandler.device.Type,
1811 "to-adapter": onuDev.deviceType,
1812 "device-id": f.deviceHandler.device.Id,
1813 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301814 return nil
1815}
1816
Neha Sharma96b7bf22020-06-15 10:37:32 +00001817func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1818 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301819 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001820 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301821 log.Fields{
1822 "intf-id": intfID,
1823 "onu-id": onuID,
1824 "uni-id": uniID,
1825 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001826 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301827 }
1828
khenaidoodc2116e2021-10-19 17:33:19 -04001829 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001830 DeviceId: onuDev.deviceID,
1831 UniId: uniID,
1832 TpInstancePath: tpPath,
1833 AllocId: allocID,
1834 }
1835
Neha Sharma96b7bf22020-06-15 10:37:32 +00001836 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301837 log.Fields{
1838 "msg": *delTcontMsg,
1839 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001840
1841 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301842 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1843 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001844 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1845 "to-adapter": onuDev.adapterEndpoint,
1846 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301847 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001848 "device-id": f.deviceHandler.device.Id}, err)
1849
Girish Gowdra6b130582019-11-20 16:45:20 +05301850 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001851 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301852 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001853 "msg": delTcontMsg,
1854 "device-id": f.deviceHandler.device.Id,
1855 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301856 return nil
1857}
1858
Girish Gowdrac3037402020-01-22 20:29:53 +05301859// Once the gemport is released for a given onu, it also has to be cleared from local cache
1860// which was used for deriving the gemport->logicalPortNo during packet-in.
1861// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1862// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001863func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001864 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301865 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001866 "gem-port-id": gemPortID,
1867 "intf-id": intfID,
1868 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001869 "device-id": f.deviceHandler.device.Id})
1870 f.onuGemInfoLock.RLock()
1871 onugem, ok := f.onuGemInfoMap[onuID]
1872 f.onuGemInfoLock.RUnlock()
1873 if !ok {
1874 logger.Warnw(ctx, "onu gem info already cleared from cache", log.Fields{
1875 "gem-port-id": gemPortID,
1876 "intf-id": intfID,
1877 "onu-id": onuID,
1878 "device-id": f.deviceHandler.device.Id})
1879 return
1880 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001881deleteLoop:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001882 for j, gem := range onugem.GemPorts {
1883 // If the gemport is found, delete it from local cache.
1884 if gem == gemPortID {
1885 onugem.GemPorts = append(onugem.GemPorts[:j], onugem.GemPorts[j+1:]...)
1886 f.onuGemInfoLock.Lock()
1887 f.onuGemInfoMap[onuID] = onugem
1888 f.onuGemInfoLock.Unlock()
1889 logger.Infow(ctx, "removed-gemport-from-local-cache",
1890 log.Fields{
1891 "intf-id": intfID,
1892 "onu-id": onuID,
1893 "deletedgemport-id": gemPortID,
1894 "gemports": onugem.GemPorts,
1895 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001896 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301897 }
1898 }
1899}
1900
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301901//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001902// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001903func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Girish Gowdra82c80982021-03-26 16:22:02 -07001904 gemPortID int32, flowID uint64, portNum uint32, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001905
Girish Gowdraa482f272021-03-24 23:04:19 -07001906 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1907 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001908 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1909 log.Fields{
1910 "tpPath": tpPath,
1911 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001912
1913 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1914
1915 if used {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001916 f.gemToFlowIDsKey.RLock()
1917 flowIDs := f.gemToFlowIDs[uint32(gemPortID)]
1918 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001919
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001920 for i, flowIDinMap := range flowIDs {
1921 if flowIDinMap == flowID {
1922 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001923 f.gemToFlowIDsKey.Lock()
1924 f.gemToFlowIDs[uint32(gemPortID)] = flowIDs
1925 f.gemToFlowIDsKey.Unlock()
1926 // everytime gemToFlowIDs cache is updated the same should be updated
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001927 // in kv store by calling UpdateFlowIDsForGem
Girish Gowdraa482f272021-03-24 23:04:19 -07001928 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001929 return err
1930 }
1931 break
1932 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001933 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001934 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1935 log.Fields{
1936 "gemport-id": gemPortID,
1937 "usedByFlows": flowIDs,
1938 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001939
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001940 return nil
1941 }
1942 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 -07001943 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001944 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), uint32(gemPortID)) // ignore error and proceed.
1945 //everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001946 // by calling DeleteFlowIDsForGem
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001947 f.gemToFlowIDsKey.Lock()
1948 delete(f.gemToFlowIDs, uint32(gemPortID))
1949 f.gemToFlowIDsKey.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001950
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001951 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1952
1953 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001954
Mahir Gunyel199570a2021-07-04 15:39:36 -07001955 //First remove TCONT from child if needed. Then remove the GEM.
1956 //It is expected from child to clean ani side conf if all GEMs of TP are deleted.
1957 //Before this, ensure that the related TCONT deletions are informed to child.
1958 //Refer to VOL-4215.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001959 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001960 if err != nil || techprofileInst == nil {
1961 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1962 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1963 if childDevice == nil {
1964 // happens when subscriber un-provision is immediately followed by child device delete
1965 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1966 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1967 return nil
1968 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001969 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1970 log.Fields{
1971 "tp-id": tpID,
1972 "path": tpPath}, err)
1973 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001974 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001975 case *tp_pb.TechProfileInstance:
Gamze Abakacb0e6772021-06-10 08:32:12 +00001976 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst, uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001977 if !ok {
Girish Gowdraa482f272021-03-24 23:04:19 -07001978 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001979 logger.Warn(ctx, err)
1980 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001981 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001982 logger.Warn(ctx, err)
1983 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001984 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 -07001985 logger.Warn(ctx, err)
1986 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001987 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 -07001988 logger.Warn(ctx, err)
1989 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001990 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001991 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07001992 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001993 logger.Warn(ctx, err)
1994 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001995 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001996 logger.Warn(ctx, err)
1997 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001998 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001999 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002000 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002001 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302002 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002003 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302004 "onu-id": onuID,
2005 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002006 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002007 "alloc-id": techprofileInst.AllocId,
2008 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002009 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002010 default:
2011 logger.Errorw(ctx, "error-unknown-tech",
2012 log.Fields{
2013 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002014 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002015
Mahir Gunyel199570a2021-07-04 15:39:36 -07002016 // Delete the gem port on the ONU. Send Gem Removal After TCONT removal.
2017 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
2018 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2019 log.Fields{
2020 "err": err,
2021 "intfID": intfID,
2022 "onu-id": onuID,
2023 "uni-id": uniID,
2024 "device-id": f.deviceHandler.device.Id,
2025 "gemport-id": gemPortID})
2026 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302027 return nil
2028}
2029
David K. Bainbridge794735f2020-02-11 21:01:37 -08002030// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002031func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002032 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302033 log.Fields{
2034 "flowDirection": flowDirection,
2035 "flow": *flow,
2036 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002037
2038 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002039 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002040 }
2041
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302042 classifierInfo := make(map[string]interface{})
2043
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002044 portNum, Intf, onu, uni, inPort, ethType, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302045 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002046 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002047 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302048 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302049
David K. Bainbridge794735f2020-02-11 21:01:37 -08002050 onuID := int32(onu)
2051 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002052 tpID, err := getTpIDFromFlow(ctx, flow)
2053 if err != nil {
2054 return olterrors.NewErrNotFound("tp-id",
2055 log.Fields{
2056 "flow": flow,
2057 "intf-id": Intf,
2058 "onu-id": onuID,
2059 "uni-id": uniID,
2060 "device-id": f.deviceHandler.device.Id}, err)
2061 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302062
2063 for _, field := range flows.GetOfbFields(flow) {
2064 if field.Type == flows.IP_PROTO {
2065 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002066 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302067 }
2068 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002069 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302070 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002071 "flow-id": flow.Id,
2072 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302073 "onu-id": onuID,
2074 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302075
2076 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2077 onuID = -1
2078 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002079 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002080 Intf, err = plt.IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002081 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002082 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002083 log.Fields{
2084 "port-number": inPort,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002085 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002086 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002087 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302088 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002089
2090 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2091 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002092 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2093 return err
2094 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002095
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002096 f.flowIDToGemsLock.Lock()
2097 gems, ok := f.flowIDToGems[flow.Id]
2098 if !ok {
2099 logger.Errorw(ctx, "flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id})
2100 f.flowIDToGemsLock.Unlock()
2101 return olterrors.NewErrNotFound("flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id}, nil)
2102 }
2103 copyOfGems := make([]uint32, len(gems))
2104 _ = copy(copyOfGems, gems)
2105 // Delete the flow-id to gemport list entry from the map now the flow is deleted.
2106 delete(f.flowIDToGems, flow.Id)
2107 f.flowIDToGemsLock.Unlock()
2108
2109 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": copyOfGems})
2110 for _, gem := range copyOfGems {
2111 if err = f.clearResources(ctx, Intf, onuID, uniID, int32(gem), flow.Id, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002112 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002113 "flow-id": flow.Id,
2114 "device-id": f.deviceHandler.device.Id,
2115 "onu-id": onuID,
2116 "intf": Intf,
2117 "gem": gem,
2118 "err": err,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002119 })
2120 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302121 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302122 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002123
Girish Gowdra82c80982021-03-26 16:22:02 -07002124 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2125 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2126 return err
2127 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002128 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002129}
2130
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002131//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002132func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002133
Matteo Scandolof16389e2021-05-18 00:47:08 +00002134 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302135 var direction string
2136 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002137
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302138 for _, action := range flows.GetActions(flow) {
2139 if action.Type == flows.OUTPUT {
2140 if out := action.GetOutput(); out != nil {
2141 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002142 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302143 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002144 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002145 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002146 }
2147 }
2148 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002149
2150 if flows.HasGroup(flow) {
2151 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002152 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002153 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302154 direction = Upstream
2155 } else {
2156 direction = Downstream
2157 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302158
Girish Gowdracefae192020-03-19 18:14:10 -07002159 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002160 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002161
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002162 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002163}
2164
Esin Karamanae41e2b2019-12-17 18:13:13 +00002165//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2166func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002167 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002168 if ethType, ok := classifierInfo[EthType]; ok {
2169 if ethType.(uint32) == IPv4EthType {
2170 if ipProto, ok := classifierInfo[IPProto]; ok {
2171 if ipProto.(uint32) == IgmpProto {
2172 return true
2173 }
2174 }
2175 }
2176 }
2177 }
2178 return false
2179}
2180
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002181// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002182func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002183 // Step1 : Fill flowControlBlock
2184 // Step2 : Push the flowControlBlock to ONU channel
2185 // Step3 : Wait on response channel for response
2186 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002187 startTime := time.Now()
2188 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002189 errChan := make(chan error)
2190 flowCb := flowControlBlock{
2191 ctx: ctx,
2192 addFlow: addFlow,
2193 flow: flow,
2194 flowMetadata: flowMetadata,
2195 errChan: &errChan,
2196 }
2197 inPort, outPort := getPorts(flow)
2198 var onuID uint32
2199 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002200 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002201 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002202 if f.flowHandlerRoutineActive[onuID] {
2203 // inPort or outPort is InvalidPort for trap-from-nni flows.
2204 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2205 // Send the flowCb on the ONU flow channel
2206 f.incomingFlows[onuID] <- flowCb
2207 // Wait on the channel for flow handlers return value
2208 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002209 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002210 return err
2211 }
2212 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2213 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002214}
2215
2216// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2217// 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 -07002218func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002219 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002220 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002221 // block on the channel to receive an incoming flow
2222 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002223 case flowCb := <-subscriberFlowChannel:
2224 if flowCb.addFlow {
2225 logger.Info(flowCb.ctx, "adding-flow-start")
2226 startTime := time.Now()
2227 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2228 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2229 // Pass the return value over the return channel
2230 *flowCb.errChan <- err
2231 } else {
2232 logger.Info(flowCb.ctx, "removing-flow-start")
2233 startTime := time.Now()
2234 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2235 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2236 // Pass the return value over the return channel
2237 *flowCb.errChan <- err
2238 }
2239 case <-stopHandler:
2240 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2241 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002242 }
2243 }
2244}
2245
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002246// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
2247func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context) {
2248 for i, v := range f.stopFlowHandlerRoutine {
2249 if f.flowHandlerRoutineActive[i] {
2250 v <- true
2251 }
2252 }
2253 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2254}
2255
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002256// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302257// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002258func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002259 classifierInfo := make(map[string]interface{})
2260 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002261 var UsMeterID uint32
2262 var DsMeterID uint32
2263
Neha Sharma96b7bf22020-06-15 10:37:32 +00002264 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302265 log.Fields{
2266 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002267 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002268 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002269
Neha Sharma96b7bf22020-06-15 10:37:32 +00002270 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002271 if err != nil {
2272 // Error logging is already done in the called function
2273 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002274 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302275 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002276
Esin Karamanccb714b2019-11-29 15:02:06 +00002277 if flows.HasGroup(flow) {
2278 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002279 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002280 }
2281
manikkaraj k17652a72019-05-06 09:06:36 -04002282 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002283 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002284 if err != nil {
2285 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002286 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002287 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002288
Neha Sharma96b7bf22020-06-15 10:37:32 +00002289 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302290 log.Fields{
2291 "classifierinfo_inport": classifierInfo[InPort],
2292 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002293 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002294
Humera Kouser94d7a842019-08-25 19:04:32 -04002295 if ethType, ok := classifierInfo[EthType]; ok {
2296 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002297 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002298 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002299 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002300 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002301 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002302 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2303 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2304 }
2305 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002306 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002307 if ipProto, ok := classifierInfo[IPProto]; ok {
2308 if ipProto.(uint32) == IPProtoDhcp {
2309 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302310 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002311 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002312 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002313 }
2314 }
2315 }
2316 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002317 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002318 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002319 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002320 }
A R Karthick1f85b802019-10-11 05:06:05 +00002321
npujarec5762e2020-01-01 14:08:48 +05302322 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002323 // also update flowmgr cache
2324 f.onuGemInfoLock.Lock()
2325 onugem, ok := f.onuGemInfoMap[onuID]
2326 if ok {
2327 found := false
2328 for _, uni := range onugem.UniPorts {
2329 if uni == portNo {
2330 found = true
2331 break
2332 }
2333 }
2334 if !found {
2335 onugem.UniPorts = append(onugem.UniPorts, portNo)
2336 f.onuGemInfoMap[onuID] = onugem
2337 logger.Infow(ctx, "added uni port to onugem cache", log.Fields{"uni": portNo})
2338 }
2339 }
2340 f.onuGemInfoLock.Unlock()
A R Karthick1f85b802019-10-11 05:06:05 +00002341
Neha Sharma96b7bf22020-06-15 10:37:32 +00002342 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002343 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302344 return olterrors.NewErrNotFound("tpid-for-flow",
2345 log.Fields{
2346 "flow": flow,
2347 "intf-id": IntfID,
2348 "onu-id": onuID,
2349 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002350 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002351 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302352 log.Fields{
2353 "tp-id": TpID,
2354 "intf-id": intfID,
2355 "onu-id": onuID,
2356 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002357 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002358 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002359 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002360 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002361 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002362 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002363
2364 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002365 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002366}
Girish Gowdra3d633032019-12-10 16:37:05 +05302367
Esin Karamanccb714b2019-11-29 15:02:06 +00002368// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002369func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302370 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002371 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302372 "classifier-info": classifierInfo,
2373 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002374
Esin Karaman65409d82020-03-18 10:58:18 +00002375 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002376 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002377 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002378 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002379
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002380 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002381
David K. Bainbridge794735f2020-02-11 21:01:37 -08002382 onuID := NoneOnuID
2383 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002384
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002385 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002386 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002387 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002388 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002389 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2390 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002391 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002392 }
2393 groupID := actionInfo[GroupID].(uint32)
2394 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002395 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002396 FlowType: Multicast,
2397 NetworkIntfId: int32(networkInterfaceID),
2398 GroupId: groupID,
2399 Classifier: classifierProto,
2400 Priority: int32(flow.Priority),
2401 Cookie: flow.Cookie}
2402
Kent Hagermane6ff1012020-07-14 15:07:53 -04002403 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002404 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002405 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002406 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002407 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002408 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002409 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002410 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002411 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002412 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002413 //cached group can be removed now
2414 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002415 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002416 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002417 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002418
David K. Bainbridge794735f2020-02-11 21:01:37 -08002419 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002420}
2421
Esin Karaman65409d82020-03-18 10:58:18 +00002422//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2423func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2424 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002425 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002426 if err != nil {
2427 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2428 }
2429 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002430 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002431
2432 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2433 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002434}
2435
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002436//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002437func (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 -07002438
Neha Sharma96b7bf22020-06-15 10:37:32 +00002439 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302440 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002441 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302442 log.Fields{
2443 "intf-id": intfID,
2444 "onu-id": onuID,
2445 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002446 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302447 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002448 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002449
Neha Sharma96b7bf22020-06-15 10:37:32 +00002450 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002451 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002452 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002453 UniId: uniID,
2454 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002455 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002456 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002457 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002458
2459 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2460 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302461 return olterrors.NewErrCommunication("send-techprofile-download-request",
2462 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002463 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302464 "to-adapter": onuDev.deviceType,
2465 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002466 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002467 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002468 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302469 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302470}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002471
Girish Gowdra197acc12021-08-16 10:59:45 -07002472//AddOnuInfoToFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2473func (f *OpenOltFlowMgr) AddOnuInfoToFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302474
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002475 f.onuGemInfoLock.RLock()
2476 _, ok := f.onuGemInfoMap[onuID]
2477 f.onuGemInfoLock.RUnlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002478 // If the ONU already exists in onuGemInfo list, nothing to do
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002479 if ok {
2480 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2481 log.Fields{"onuID": onuID,
2482 "serialNum": serialNum})
2483 return nil
Girish Gowdra9602eb42020-09-09 15:50:39 -07002484 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002485
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002486 onuGemInfo := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2487 f.onuGemInfoLock.Lock()
2488 f.onuGemInfoMap[onuID] = &onuGemInfo
2489 f.onuGemInfoLock.Unlock()
2490 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onuID, onuGemInfo); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002491 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302492 }
Girish Gowdra197acc12021-08-16 10:59:45 -07002493 logger.Infow(ctx, "added-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302494 log.Fields{
2495 "intf-id": intfID,
2496 "onu-id": onuID,
2497 "serial-num": serialNum,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002498 "onu": onuGemInfo,
Shrey Baid26912972020-04-16 21:02:31 +05302499 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002500 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002501}
2502
Girish Gowdra197acc12021-08-16 10:59:45 -07002503//RemoveOnuInfoFromFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2504func (f *OpenOltFlowMgr) RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32) error {
2505
2506 f.onuGemInfoLock.Lock()
2507 delete(f.onuGemInfoMap, onuID)
2508 f.onuGemInfoLock.Unlock()
2509
2510 if err := f.resourceMgr.DelOnuGemInfo(ctx, intfID, onuID); err != nil {
2511 return err
2512 }
2513 logger.Infow(ctx, "deleted-onuinfo",
2514 log.Fields{
2515 "intf-id": intfID,
2516 "onu-id": onuID,
2517 "device-id": f.deviceHandler.device.Id})
2518 return nil
2519}
2520
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302521//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302522func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002523
Neha Sharma96b7bf22020-06-15 10:37:32 +00002524 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302525 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002526 "gem-port-id": gemPort,
2527 "intf-id": intfID,
2528 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002529 "device-id": f.deviceHandler.device.Id})
2530 f.onuGemInfoLock.RLock()
2531 onugem, ok := f.onuGemInfoMap[onuID]
2532 f.onuGemInfoLock.RUnlock()
2533 if !ok {
2534 logger.Warnw(ctx, "onu gem info is missing", log.Fields{
2535 "gem-port-id": gemPort,
2536 "intf-id": intfID,
2537 "onu-id": onuID,
2538 "device-id": f.deviceHandler.device.Id})
2539 return
2540 }
2541
2542 if onugem.OnuID == onuID {
2543 // check if gem already exists , else update the cache and kvstore
2544 for _, gem := range onugem.GemPorts {
2545 if gem == gemPort {
2546 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2547 log.Fields{
2548 "gem": gemPort,
2549 "device-id": f.deviceHandler.device.Id})
2550 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302551 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302552 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002553 onugem.GemPorts = append(onugem.GemPorts, gemPort)
2554 f.onuGemInfoLock.Lock()
2555 f.onuGemInfoMap[onuID] = onugem
2556 f.onuGemInfoLock.Unlock()
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002557 logger.Debugw(ctx, "updated onu gem info from cache", log.Fields{"onugem": onugem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002558 } else {
2559 logger.Warnw(ctx, "mismatched onu id", log.Fields{
2560 "gem-port-id": gemPort,
2561 "intf-id": intfID,
2562 "onu-id": onuID,
2563 "device-id": f.deviceHandler.device.Id})
2564 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302565 }
npujarec5762e2020-01-01 14:08:48 +05302566 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302567 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002568 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302569 log.Fields{
2570 "intf-id": intfID,
2571 "onu-id": onuID,
2572 "gemPort": gemPort,
2573 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002574 return
2575 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002576 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302577 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002578 "gem-port-id": gemPort,
2579 "intf-id": intfID,
2580 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002581 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002582}
2583
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002584//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302585func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002586 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002587
2588 if packetIn.IntfType == "pon" {
2589 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002590 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002591 onuID, uniID := packetIn.OnuId, packetIn.UniId
2592 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 +00002593
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002594 if packetIn.PortNo != 0 {
2595 logicalPortNum = packetIn.PortNo
2596 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002597 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002598 }
2599 // 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 +00002600 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002601 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002602 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002603 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002604
2605 if logger.V(log.DebugLevel) {
2606 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2607 log.Fields{
2608 "logical-port-num": logicalPortNum,
2609 "intf-type": packetIn.IntfType,
2610 "packet": hex.EncodeToString(packetIn.Pkt),
2611 })
2612 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002613 return logicalPortNum, nil
2614}
2615
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002616//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002617func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002618 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002619
2620 ctag, priority, err := getCTagFromPacket(ctx, packet)
2621 if err != nil {
2622 return 0, err
2623 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302624
Esin Karaman7fb80c22020-07-16 14:23:33 +00002625 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002626 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002627 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002628 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002629 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302630 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002631 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302632 log.Fields{
2633 "pktinkey": pktInkey,
2634 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002635
2636 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002637 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302638 //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 +00002639 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302640 if err == nil {
2641 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002642 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302643 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002644 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002645 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302646 log.Fields{
2647 "pktinkey": pktInkey,
2648 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302649 return gemPortID, nil
2650 }
2651 }
Shrey Baid26912972020-04-16 21:02:31 +05302652 return uint32(0), olterrors.NewErrNotFound("gem-port",
2653 log.Fields{
2654 "pktinkey": pktInkey,
2655 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002656
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002657}
2658
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002659func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2660 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002661 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002662 classifier[PacketTagType] = DoubleTag
2663 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002664 /* We manage flowId resource pool on per PON port basis.
2665 Since this situation is tricky, as a hack, we pass the NNI port
2666 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002667 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002668 on NNI port, use onu_id as -1 (invalid)
2669 ****************** CAVEAT *******************
2670 This logic works if the NNI Port Id falls within the same valid
2671 range of PON Port Ids. If this doesn't work for some OLT Vendor
2672 we need to have a re-look at this.
2673 *********************************************
2674 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002675 onuID := -1
2676 uniID := -1
2677 gemPortID := -1
2678 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002679 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302680 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302681 return olterrors.NewErrNotFound("nni-intreface-id",
2682 log.Fields{
2683 "classifier": classifier,
2684 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002685 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302686 }
2687
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002688 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002689 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002690 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002691 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002692
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002693 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2694 log.Fields{
2695 "classifier": classifier,
2696 "action": action,
2697 "flowId": logicalFlow.Id,
2698 "intf-id": networkInterfaceID})
2699
David K. Bainbridge794735f2020-02-11 21:01:37 -08002700 classifierProto, err := makeOpenOltClassifierField(classifier)
2701 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002702 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002703 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002704 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002705 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002706 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002707 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002708 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002709 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002710 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2711 OnuId: int32(onuID), // OnuId not required
2712 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002713 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002714 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002715 AllocId: int32(allocID), // AllocId not used
2716 NetworkIntfId: int32(networkInterfaceID),
2717 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002718 Classifier: classifierProto,
2719 Action: actionProto,
2720 Priority: int32(logicalFlow.Priority),
2721 Cookie: logicalFlow.Cookie,
2722 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002723 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002724 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002725 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002726 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002727 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002728}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002729
Esin Karamanae41e2b2019-12-17 18:13:13 +00002730//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2731func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2732 var packetType string
2733 ovid, ivid := false, false
2734 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2735 vid := vlanID & VlanvIDMask
2736 if vid != ReservedVlan {
2737 ovid = true
2738 }
2739 }
2740 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2741 vid := uint32(metadata)
2742 if vid != ReservedVlan {
2743 ivid = true
2744 }
2745 }
2746 if ovid && ivid {
2747 packetType = DoubleTag
2748 } else if !ovid && !ivid {
2749 packetType = Untagged
2750 } else {
2751 packetType = SingleTag
2752 }
2753 return packetType
2754}
2755
2756//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002757func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002758 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002759 action := make(map[string]interface{})
2760 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2761 action[TrapToHost] = true
2762 /* We manage flowId resource pool on per PON port basis.
2763 Since this situation is tricky, as a hack, we pass the NNI port
2764 index (network_intf_id) as PON port Index for the flowId resource
2765 pool. Also, there is no ONU Id available for trapping packets
2766 on NNI port, use onu_id as -1 (invalid)
2767 ****************** CAVEAT *******************
2768 This logic works if the NNI Port Id falls within the same valid
2769 range of PON Port Ids. If this doesn't work for some OLT Vendor
2770 we need to have a re-look at this.
2771 *********************************************
2772 */
2773 onuID := -1
2774 uniID := -1
2775 gemPortID := -1
2776 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002777 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002778 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302779 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002780 "classifier": classifier,
2781 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002782 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002783 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002784 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002785 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002786 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002787 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002788
David K. Bainbridge794735f2020-02-11 21:01:37 -08002789 classifierProto, err := makeOpenOltClassifierField(classifier)
2790 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002791 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002792 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002793 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002794 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002795 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002796 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002797 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002798 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002799 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2800 OnuId: int32(onuID), // OnuId not required
2801 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002802 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002803 FlowType: Downstream,
2804 AllocId: int32(allocID), // AllocId not used
2805 NetworkIntfId: int32(networkInterfaceID),
2806 GemportId: int32(gemPortID), // GemportId not used
2807 Classifier: classifierProto,
2808 Action: actionProto,
2809 Priority: int32(logicalFlow.Priority),
2810 Cookie: logicalFlow.Cookie,
2811 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002812 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002813 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002814 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002815 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002816
David K. Bainbridge794735f2020-02-11 21:01:37 -08002817 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002818}
2819
salmansiddiqui7ac62132019-08-22 03:58:50 +00002820func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2821 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302822 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002823 }
2824 if Dir == tp_pb.Direction_UPSTREAM {
2825 return "upstream", nil
2826 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2827 return "downstream", nil
2828 }
2829 return "", nil
2830}
2831
Kent Hagermane6ff1012020-07-14 15:07:53 -04002832// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302833func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002834 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002835 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002836 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002837 intfID := args[IntfID]
2838 onuID := args[OnuID]
2839 uniID := args[UniID]
2840 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002841 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002842 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002843 gemToAes := make(map[uint32]bool)
2844
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002845 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002846 var direction = tp_pb.Direction_UPSTREAM
2847 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002848 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002849 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002850 attributes = TpInst.UpstreamGemPortAttributeList
2851 } else {
2852 attributes = TpInst.DownstreamGemPortAttributeList
2853 direction = tp_pb.Direction_DOWNSTREAM
2854 }
2855 default:
2856 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002857 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002858 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002859
2860 if len(gemPorts) == 1 {
2861 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002862 gemPortID = gemPorts[0]
2863 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002864 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2865 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002866 pBitMap := attributes[idx].PbitMap
2867 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2868 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2869 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002870 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002871 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2872 if pbitSet == pbit1 {
2873 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2874 pbitToGem[pcp] = gemID
2875 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002876 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002877 }
2878 }
2879 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002880 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2881 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2882 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002883 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002884 }
2885
Gamze Abaka7650be62021-02-26 10:50:36 +00002886 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2887 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2888
salmansiddiqui7ac62132019-08-22 03:58:50 +00002889 if ipProto, ok := classifierInfo[IPProto]; ok {
2890 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002891 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002892 "tp-id": tpID,
2893 "alloc-id": allocID,
2894 "intf-id": intfID,
2895 "onu-id": onuID,
2896 "uni-id": uniID,
2897 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002898 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002899 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002900 logger.Warn(ctx, err)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002901 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002902 }
2903
Girish Gowdra32625212020-04-29 11:26:35 -07002904 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002905 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302906 log.Fields{
2907 "intf-id": intfID,
2908 "onu-id": onuID,
2909 "uni-id": uniID,
2910 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002911 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002912 logger.Warn(ctx, err)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002913 return 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})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002917 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002918 }
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)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002935 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002936 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002937 } else if ethType.(uint32) == PPPoEDEthType {
2938 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2939 "tp-id": tpID,
2940 "alloc-id": allocID,
2941 "intf-id": intfID,
2942 "onu-id": onuID,
2943 "uni-id": uniID,
2944 })
2945 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002946 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002947 logger.Warn(ctx, err)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002948 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002949 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002950 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002951 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002952 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002953 "intf-id": intfID,
2954 "onu-id": onuID,
2955 "uni-id": uniID,
2956 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002957 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002958 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002959 logger.Warn(ctx, err)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002960 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002961 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002962 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002963 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002964 "intf-id": intfID,
2965 "onu-id": onuID,
2966 "uni-id": uniID,
2967 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002968 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002969 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002970 logger.Warn(ctx, err)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002971 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002972 }
2973 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002974 return olterrors.NewErrInvalidValue(log.Fields{
2975 "intf-id": intfID,
2976 "onu-id": onuID,
2977 "uni-id": uniID,
2978 "classifier": classifierInfo,
2979 "action": actionInfo,
2980 "flow": flow},
2981 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002982 }
2983 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002984 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002985 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002986 logger.Warn(ctx, err)
2987 }
2988 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002989 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00002990}
2991
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002992func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002993 f.gemToFlowIDsKey.RLock()
2994 flowIDList := f.gemToFlowIDs[gemPortID]
2995 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002996 return len(flowIDList) > 1
2997
Gamze Abakafee36392019-10-03 11:17:24 +00002998}
2999
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003000func (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 +05303001 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003002 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3003 for _, currentGemPort := range currentGemPorts {
3004 for _, tpGemPort := range tpGemPorts {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003005 if (currentGemPort == tpGemPort.GemportId) && (currentGemPort != gemPortID) {
Gamze Abakafee36392019-10-03 11:17:24 +00003006 return true, currentGemPort
3007 }
3008 }
3009 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003010 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
3011 return false, 0
3012}
Girish Gowdra54934262019-11-13 14:19:55 +05303013
Gamze Abakacb0e6772021-06-10 08:32:12 +00003014func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003015 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
3016 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
3017 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 +00003018 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303019 for i := 0; i < len(tpInstances); i++ {
3020 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00003021 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003022 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Gamze Abakacb0e6772021-06-10 08:32:12 +00003023 logger.Debugw(ctx, "alloc-is-in-use",
3024 log.Fields{
3025 "device-id": f.deviceHandler.device.Id,
3026 "intfID": sq.intfID,
3027 "onuID": sq.onuID,
3028 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003029 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00003030 })
3031 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303032 }
3033 }
3034 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003035 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003036}
3037
Neha Sharma96b7bf22020-06-15 10:37:32 +00003038func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003039 for _, field := range flows.GetOfbFields(flow) {
3040 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003041 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003042 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003043 } else if field.Type == flows.ETH_DST {
3044 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003045 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003046 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003047 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003048 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003049 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003050 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003051 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003052 } else if field.Type == flows.VLAN_VID {
Andrea Campanellafaa42152021-10-28 11:50:56 +05303053 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3054 if field.GetVlanVid() != ReservedVlan {
3055 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3056 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3057 }
Scott Baker355d1742019-10-24 10:57:52 -07003058 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003059 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003060 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003061 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003062 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003063 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003064 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003065 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003066 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003067 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003068 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003069 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003070 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003071 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003072 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003073 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003074 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003075 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003076 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003077 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003078 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003079 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003080 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003081 return
3082 }
3083 }
3084}
3085
Neha Sharma96b7bf22020-06-15 10:37:32 +00003086func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003087 for _, action := range flows.GetActions(flow) {
3088 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003089 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003090 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003091 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003092 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003093 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003094 }
Scott Baker355d1742019-10-24 10:57:52 -07003095 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003096 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003097 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003098 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003099 if out := action.GetPush(); out != nil {
3100 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003101 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003102 } else {
3103 actionInfo[PushVlan] = true
3104 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003105 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303106 log.Fields{
3107 "push-tpid": actionInfo[TPID].(uint32),
3108 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003109 }
3110 }
Scott Baker355d1742019-10-24 10:57:52 -07003111 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003112 if out := action.GetSetField(); out != nil {
3113 if field := out.GetField(); field != nil {
3114 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003115 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003116 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003117 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3118 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003119 }
3120 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003121 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003122 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003123 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003124 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003125 }
3126 }
3127 return nil
3128}
3129
Neha Sharma96b7bf22020-06-15 10:37:32 +00003130func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003131 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003132 fieldtype := ofbField.GetType()
3133 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003134 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3135 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003136 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003137 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003138 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003139 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003140 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3141 pcp := ofbField.GetVlanPcp()
3142 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003143 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003144 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003145 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003146 }
3147 }
3148}
3149
Neha Sharma96b7bf22020-06-15 10:37:32 +00003150func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003151 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003152 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003153 } else {
3154 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003155 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003156 }
3157}
3158
Neha Sharma96b7bf22020-06-15 10:37:32 +00003159func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003160 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003161 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003162 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003163 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003164 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003165 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003166 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303167 log.Fields{
3168 "newinport": classifierInfo[InPort].(uint32),
3169 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003170 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303171 return olterrors.NewErrNotFound("child-in-port",
3172 log.Fields{
3173 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3174 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003175 }
3176 }
3177 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003178 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003179 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003180 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003181 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003182 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003183 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303184 log.Fields{
3185 "newoutport": actionInfo[Output].(uint32),
3186 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003187 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303188 return olterrors.NewErrNotFound("out-port",
3189 log.Fields{
3190 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3191 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003192 }
3193 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003194 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003195 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003196 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003197 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303198 log.Fields{
3199 "newinport": actionInfo[Output].(uint32),
3200 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003201 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303202 return olterrors.NewErrNotFound("nni-port",
3203 log.Fields{
3204 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3205 "in-port": classifierInfo[InPort].(uint32),
3206 "out-port": actionInfo[Output].(uint32),
3207 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003208 }
3209 }
3210 }
3211 return nil
3212}
Gamze Abakafee36392019-10-03 11:17:24 +00003213
Neha Sharma96b7bf22020-06-15 10:37:32 +00003214func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003215 /* Metadata 8 bytes:
3216 Most Significant 2 Bytes = Inner VLAN
3217 Next 2 Bytes = Tech Profile ID(TPID)
3218 Least Significant 4 Bytes = Port ID
3219 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3220 subscriber related flows.
3221 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003222 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003223 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003224 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003225 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003226 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003227 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003228}
3229
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003230func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3231 for _, sliceElement := range slice {
3232 if sliceElement == item {
3233 return slice
3234 }
3235 }
3236 return append(slice, item)
3237}
3238
3239func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003240 for _, sliceElement := range slice {
3241 if sliceElement == item {
3242 return slice
3243 }
3244 }
3245 return append(slice, item)
3246}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303247
3248// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003249func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303250
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003251 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303252 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003253 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003254 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003255 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003256 log.Fields{
3257 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003258 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003259 return uint32(0), err
3260 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003261 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303262 return intfID, nil
3263 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003264 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003265 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003266 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003267 log.Fields{
3268 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003269 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003270 return uint32(0), err
3271 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003272 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303273 return intfID, nil
3274 }
3275 return uint32(0), nil
3276}
3277
3278// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003279func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3280 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3281 if err != nil {
3282 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3283 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3284 return
3285 }
3286 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003287
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003288 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003289 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003290 f.packetInGemPortLock.RUnlock()
3291
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303292 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003293 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003294 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 +05303295 log.Fields{
3296 "pktinkey": pktInkey,
3297 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003298 return
3299 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303300 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003301 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003302 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003303 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003304
npujarec5762e2020-01-01 14:08:48 +05303305 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003306 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 +05303307 log.Fields{
3308 "pktinkey": pktInkey,
3309 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303310}
3311
Esin Karaman7fb80c22020-07-16 14:23:33 +00003312//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3313func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3314 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003315 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003316 return 0, 0, errors.New("invalid packet length")
3317 }
3318 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3319 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3320
3321 var index int8
3322 if outerEthType == 0x8100 {
3323 if innerEthType == 0x8100 {
3324 // q-in-q 802.1ad or 802.1q double tagged packet.
3325 // get the inner vlanId
3326 index = 18
3327 } else {
3328 index = 14
3329 }
3330 priority := (packet[index] >> 5) & 0x7
3331 //13 bits composes vlanId value
3332 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3333 return vlan, priority, nil
3334 }
3335 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3336 return 0, 0, nil
3337}
3338
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003339func (f *OpenOltFlowMgr) loadFlowIDsForGemAndGemIDsForFlow(ctx context.Context) {
3340 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - start")
3341 f.onuGemInfoLock.RLock()
3342 f.gemToFlowIDsKey.Lock()
3343 f.flowIDToGemsLock.Lock()
3344 for _, og := range f.onuGemInfoMap {
3345 for _, gem := range og.GemPorts {
3346 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, f.ponPortIdx, gem)
Gamze Abaka6f345c12021-09-08 01:14:33 +00003347 if err == nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003348 f.gemToFlowIDs[gem] = flowIDs
3349 for _, flowID := range flowIDs {
3350 if _, ok := f.flowIDToGems[flowID]; !ok {
3351 f.flowIDToGems[flowID] = []uint32{gem}
3352 } else {
3353 f.flowIDToGems[flowID] = appendUnique32bit(f.flowIDToGems[flowID], gem)
3354 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303355 }
3356 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303357 }
3358 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003359 f.flowIDToGemsLock.Unlock()
3360 f.gemToFlowIDsKey.Unlock()
3361 f.onuGemInfoLock.RUnlock()
3362 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - end")
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303363}
Esin Karamanccb714b2019-11-29 15:02:06 +00003364
Girish Gowdra9602eb42020-09-09 15:50:39 -07003365//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3366// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003367func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003368 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003369 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3370 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003371 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003372 "flow-id": flow.Id,
3373 "device-id": f.deviceHandler.device.Id})
3374 // Remove from device
3375 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3376 // DKB
3377 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3378 log.Fields{
3379 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003380 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003381 return err
3382 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003383
3384 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003385}
3386
khenaidoodc2116e2021-10-19 17:33:19 -04003387func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003388 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003389 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003390 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003391 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003392 }
3393
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003394 switch tpInst := tpInst.(type) {
3395 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003396 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003397 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003398 DeviceId: onuDeviceID,
3399 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003400 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003401 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003402 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003403 case *tp_pb.EponTechProfileInstance:
3404 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003405 DeviceId: onuDeviceID,
3406 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003407 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003408 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003409 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003410 default:
3411 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003412 }
khenaidoodc2116e2021-10-19 17:33:19 -04003413 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003414 DeviceId: onuDeviceID,
3415 UniId: uniID,
3416 TpInstancePath: tpPath,
3417 TechTpInstance: nil,
3418 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003419}
3420
Girish Gowdrabcf98af2021-07-01 08:24:42 -07003421func (f *OpenOltFlowMgr) getOnuGemInfoList(ctx context.Context) []rsrcMgr.OnuGemInfo {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003422 var onuGemInfoLst []rsrcMgr.OnuGemInfo
3423 f.onuGemInfoLock.RLock()
3424 defer f.onuGemInfoLock.RUnlock()
3425 for _, v := range f.onuGemInfoMap {
3426 onuGemInfoLst = append(onuGemInfoLst, *v)
3427 }
3428 return onuGemInfoLst
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003429}