blob: a868d2a82c46cefce8e3eb0d30098fb3c713cc5f [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"
38 ic "github.com/opencord/voltha-protos/v5/go/inter_container"
39 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
169 flowMetadata *voltha.FlowMetadata
170}
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 {
192 ctx context.Context // Flow handler context
193 addFlow bool // if true flow to be added, else removed
194 flow *voltha.OfpFlowStats // Flow message
195 flowMetadata *voltha.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,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200323 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000324 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530325 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700326 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530327
Neha Sharma96b7bf22020-06-15 10:37:32 +0000328 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530329 "device-id": f.deviceHandler.device.Id,
330 "intf-id": intfID,
331 "onu-id": onuID,
332 "uni-id": uniID,
333 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700334 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530335 "action": actionInfo,
336 "usmeter-iD": UsMeterID,
337 "dsmeter-iD": DsMeterID,
338 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400339 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
340 // is because the flow is an NNI flow and there would be no onu resources associated with it
341 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400342 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200343 cause := "no-onu-id-for-flow"
344 fields := log.Fields{
345 "onu": onuID,
346 "port-no": portNo,
347 "classifer": classifierInfo,
348 "action": actionInfo,
349 "device-id": f.deviceHandler.device.Id}
350 logger.Errorw(ctx, cause, fields)
351 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530352 }
353
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700354 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000355 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530356 "uni": uni,
357 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530358
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700359 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
360 "device-id": f.deviceHandler.device.Id,
361 "intf-id": intfID,
362 "onu-id": onuID,
363 "uni-id": uniID,
364 "port-no": portNo,
365 "classifier": classifierInfo,
366 "action": actionInfo,
367 "usmeter-id": UsMeterID,
368 "dsmeter-id": DsMeterID,
369 "tp-id": TpID})
370 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
371 if allocID == 0 || gemPorts == nil || TpInst == nil {
372 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
373 return olterrors.NewErrNotFound(
374 "alloc-id-gem-ports-tp-unavailable",
375 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400376 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700377 args := make(map[string]uint32)
378 args[IntfID] = intfID
379 args[OnuID] = onuID
380 args[UniID] = uniID
381 args[PortNo] = portNo
382 args[AllocID] = allocID
383
384 /* Flows can be added specific to gemport if p-bits are received.
385 * If no pbit mentioned then adding flows for all gemports
386 */
387 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
388
Andrea Campanellabfe08432020-09-11 17:07:03 +0200389 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530390}
391
salmansiddiqui7ac62132019-08-22 03:58:50 +0000392// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530393func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400394
Neha Sharma96b7bf22020-06-15 10:37:32 +0000395 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530396 log.Fields{"dir": sq.direction,
397 "intf-id": sq.intfID,
398 "onu-id": sq.onuID,
399 "uni-id": sq.uniID,
400 "tp-id": sq.tpID,
401 "meter-id": sq.meterID,
402 "tp-inst": sq.tpInst,
403 "flowmetadata": sq.flowMetadata,
404 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400405
Gamze Abakafee36392019-10-03 11:17:24 +0000406 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000407 if err != nil {
408 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400409 }
410
411 /* Lets make a simple assumption that if the meter-id is present on the KV store,
412 * then the scheduler and queues configuration is applied on the OLT device
413 * in the given direction.
414 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000415
Manikkaraj kb1d51442019-07-23 10:41:02 -0400416 var SchedCfg *tp_pb.SchedulerConfig
Girish Gowdraa482f272021-03-24 23:04:19 -0700417 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400418 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530419 return olterrors.NewErrNotFound("meter",
420 log.Fields{"intf-id": sq.intfID,
421 "onu-id": sq.onuID,
422 "uni-id": sq.uniID,
423 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400424 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000425
Girish Gowdraa482f272021-03-24 23:04:19 -0700426 if meterInfo != nil {
427 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id, "meter-id": sq.meterID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700428 if meterInfo.MeterID == sq.meterID {
Girish Gowdraa482f272021-03-24 23:04:19 -0700429 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
430 return err
431 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400433 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530434 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800435 "unsupported": "meter-id",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700436 "kv-store-meter-id": meterInfo.MeterID,
Shrey Baid26912972020-04-16 21:02:31 +0530437 "meter-id-in-flow": sq.meterID,
438 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400439 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000440
Neha Sharma96b7bf22020-06-15 10:37:32 +0000441 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530442 log.Fields{
443 "meter-id": sq.meterID,
444 "direction": Direction,
445 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000446
Gamze Abakafee36392019-10-03 11:17:24 +0000447 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700448 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Gamze Abakafee36392019-10-03 11:17:24 +0000449 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700450 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Girish Kumar8f73fe02019-12-09 13:19:37 +0000451 }
452
Girish Gowdraa482f272021-03-24 23:04:19 -0700453 found := false
454 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000455 if sq.flowMetadata != nil {
456 for _, meter := range sq.flowMetadata.Meters {
457 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700458 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700459 meterInfo.RefCnt = 1 // initialize it to 1, since this is the first flow that referenced the meter id.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000460 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700461 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530462 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700463 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400464 break
465 }
466 }
467 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000468 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400469 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700470 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530471 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800472 "reason": "Could-not-get-meterbands-from-flowMetadata",
473 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530474 "meter-id": sq.meterID,
475 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400476 }
Gamze Abaka01174422021-03-10 06:55:27 +0000477
478 var TrafficShaping *tp_pb.TrafficShapingInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700479 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
Gamze Abaka01174422021-03-10 06:55:27 +0000480 return olterrors.NewErrInvalidValue(log.Fields{
481 "reason": "invalid-meter-config",
482 "meter-id": sq.meterID,
483 "device-id": f.deviceHandler.device.Id}, nil)
484 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400485
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700486 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000487 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400488
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700489 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530490 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
491 log.Fields{"intf-id": sq.intfID,
492 "direction": sq.direction,
493 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400494 }
495
salmansiddiqui7ac62132019-08-22 03:58:50 +0000496 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400497 * store the meter id on the KV store, for further reference.
498 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700499 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530500 return olterrors.NewErrAdapter("failed-updating-meter-id",
501 log.Fields{"onu-id": sq.onuID,
502 "meter-id": sq.meterID,
503 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400504 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000505 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530506 log.Fields{"direction": Direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700507 "meter-info": meterInfo,
508 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400509 return nil
510}
511
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700512func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700513 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000514
515 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530516 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
517 log.Fields{"intf-id": sq.intfID,
518 "direction": sq.direction,
519 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000520 }
521
Gamze Abakacb0e6772021-06-10 08:32:12 +0000522 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
523 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
524 log.Fields{
525 "direction": sq.direction,
526 "TrafficScheds": TrafficSched,
527 "device-id": f.deviceHandler.device.Id,
528 "intfID": sq.intfID,
529 "onuID": sq.onuID,
530 "uniID": sq.uniID})
531 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
532 IntfId: sq.intfID, OnuId: sq.onuID,
533 UniId: sq.uniID, PortNo: sq.uniPort,
534 TrafficScheds: TrafficSched}); err != nil {
535 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
536 }
537 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
538 "direction": sq.direction,
539 "traffic-queues": trafficQueues,
540 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000541 }
542
543 // On receiving the CreateTrafficQueues request, the driver should create corresponding
544 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000545 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530546 log.Fields{"direction": sq.direction,
547 "traffic-queues": trafficQueues,
548 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530549 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000550 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
551 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000552 TrafficQueues: trafficQueues,
553 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530554 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000555 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000556 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530557 "direction": sq.direction,
558 "traffic-queues": trafficQueues,
559 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000560
Esin Karamanccb714b2019-11-29 15:02:06 +0000561 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700562 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000563 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700564 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present { //assumed that there is only one queue per PON for the multicast service
Esin Karamanccb714b2019-11-29 15:02:06 +0000565 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
566 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000567 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000568 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700569 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000570 gemPortID: multicastQueuePerPonPort.GemportId,
571 servicePriority: multicastQueuePerPonPort.Priority,
572 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700573 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000574 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400575 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700576 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400577 return err
578 }
Shrey Baid26912972020-04-16 21:02:31 +0530579
Neha Sharma96b7bf22020-06-15 10:37:32 +0000580 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000581 }
582 }
583 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000584 return nil
585}
586
salmansiddiqui7ac62132019-08-22 03:58:50 +0000587// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530588func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400589
590 var Direction string
591 var SchedCfg *tp_pb.SchedulerConfig
592 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000593 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530594 log.Fields{
595 "direction": sq.direction,
596 "intf-id": sq.intfID,
597 "onu-id": sq.onuID,
598 "uni-id": sq.uniID,
599 "uni-port": sq.uniPort,
600 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000601 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700602 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400603 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000604 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700605 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400606 Direction = "downstream"
607 }
608
Girish Gowdraa482f272021-03-24 23:04:19 -0700609 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
Manikkaraj kb1d51442019-07-23 10:41:02 -0400610
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700611 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000612 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000613
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700614 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000615 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530616 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
617 log.Fields{
618 "intf-id": sq.intfID,
619 "direction": sq.direction,
620 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000621 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400622
npujarec5762e2020-01-01 14:08:48 +0530623 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000624 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
625 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000626 TrafficQueues: TrafficQueues,
627 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000628 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530629 log.Fields{
630 "intf-id": sq.intfID,
631 "traffic-queues": TrafficQueues,
632 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400633 }
Gamze Abakacb0e6772021-06-10 08:32:12 +0000634 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400635
Gamze Abakacb0e6772021-06-10 08:32:12 +0000636 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
637 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
638 IntfId: sq.intfID, OnuId: sq.onuID,
639 UniId: sq.uniID, PortNo: sq.uniPort,
640 TrafficScheds: TrafficSched}); err != nil {
641 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
642 log.Fields{
643 "intf-id": sq.intfID,
644 "traffic-schedulers": TrafficSched,
645 "onu-id": sq.onuID,
646 "uni-id": sq.uniID,
647 "uni-port": sq.uniPort}, err)
648 }
649
650 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
651 log.Fields{"device-id": f.deviceHandler.device.Id,
652 "intf-id": sq.intfID,
653 "onu-id": sq.onuID,
654 "uni-id": sq.uniID,
655 "uni-port": sq.uniPort})
656
657 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700658 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
Gamze Abakacb0e6772021-06-10 08:32:12 +0000659 f.resourceMgr.FreeAllocID(ctx, sq.intfID, sq.onuID, sq.uniID, allocID)
660 // Delete the TCONT on the ONU.
661 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
662 tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
663 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
664 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
665 log.Fields{
666 "intf": sq.intfID,
667 "onu-id": sq.onuID,
668 "uni-id": sq.uniID,
669 "device-id": f.deviceHandler.device.Id,
670 "alloc-id": allocID})
671 }
672 }
673 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000674
675 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400676 * delete the meter id on the KV store.
677 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700678 err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400679 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530680 return olterrors.NewErrAdapter("unable-to-remove-meter",
681 log.Fields{
682 "onu": sq.onuID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700683 "device-id": f.deviceHandler.device.Id,
684 "intf-id": sq.intfID,
685 "onu-id": sq.onuID,
686 "uni-id": sq.uniID,
687 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400688 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000689 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530690 log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530691 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700692 "device-id": f.deviceHandler.device.Id,
693 "intf-id": sq.intfID,
694 "onu-id": sq.onuID,
695 "uni-id": sq.uniID,
696 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400697 return err
698}
699
Girish Gowdra197acc12021-08-16 10:59:45 -0700700// We are trying to force remove the schedulers and queues here if one exists for the given key.
701// We ignore any errors encountered in the process. The errors most likely are encountered when
702// the schedulers and queues are already cleared for the given key.
703func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
704
705 var schedCfg *tp_pb.SchedulerConfig
706 var err error
707 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
708 log.Fields{
709 "direction": sq.direction,
710 "intf-id": sq.intfID,
711 "onu-id": sq.onuID,
712 "uni-id": sq.uniID,
713 "uni-port": sq.uniPort,
714 "tp-id": sq.tpID,
715 "device-id": f.deviceHandler.device.Id})
716 if sq.direction == tp_pb.Direction_UPSTREAM {
717 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
718 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
719 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
720 }
721
722 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
723 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
724 TrafficSched[0].TechProfileId = sq.tpID
725
726 // Remove traffic queues. Ignore any errors, just log them.
727 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
728 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
729 "direction": sq.direction,
730 "intf-id": sq.intfID,
731 "onu-id": sq.onuID,
732 "uni-id": sq.uniID,
733 "uni-port": sq.uniPort,
734 "tp-id": sq.tpID,
735 "device-id": f.deviceHandler.device.Id,
736 "err": err})
737 } else {
738 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
739 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
740 UniId: sq.uniID, PortNo: sq.uniPort,
741 TrafficQueues: TrafficQueues,
742 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
743 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
744 "direction": sq.direction,
745 "intf-id": sq.intfID,
746 "onu-id": sq.onuID,
747 "uni-id": sq.uniID,
748 "uni-port": sq.uniPort,
749 "tp-id": sq.tpID,
750 "device-id": f.deviceHandler.device.Id,
751 "err": err})
752
753 } else {
754 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
755 "direction": sq.direction,
756 "intf-id": sq.intfID,
757 "onu-id": sq.onuID,
758 "uni-id": sq.uniID,
759 "uni-port": sq.uniPort,
760 "tp-id": sq.tpID})
761 }
762 }
763
764 // Remove traffic schedulers. Ignore any errors, just log them.
765 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
766 IntfId: sq.intfID, OnuId: sq.onuID,
767 UniId: sq.uniID, PortNo: sq.uniPort,
768 TrafficScheds: TrafficSched}); err != nil {
769 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
770 "direction": sq.direction,
771 "intf-id": sq.intfID,
772 "onu-id": sq.onuID,
773 "uni-id": sq.uniID,
774 "uni-port": sq.uniPort,
775 "tp-id": sq.tpID,
776 "device-id": f.deviceHandler.device.Id,
777 "err": err})
778 } else {
779 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
780 "direction": sq.direction,
781 "intf-id": sq.intfID,
782 "onu-id": sq.onuID,
783 "uni-id": sq.uniID,
784 "uni-port": sq.uniPort,
785 "tp-id": sq.tpID})
786 }
787}
788
Gamze Abakafee36392019-10-03 11:17:24 +0000789// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700790func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) (uint32, []uint32, interface{}) {
Gamze Abakafee36392019-10-03 11:17:24 +0000791 var allocIDs []uint32
792 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530793 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530794 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000795 var err error
npujarec5762e2020-01-01 14:08:48 +0530796 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
797 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000798 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530799
Neha Sharma96b7bf22020-06-15 10:37:32 +0000800 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530801 "intf-id": intfID,
802 "onu-id": onuID,
803 "uni-id": uniID,
804 "device-id": f.deviceHandler.device.Id,
805 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530806
Manikkaraj kb1d51442019-07-23 10:41:02 -0400807 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700808 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000809 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000810 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530811 log.Fields{
812 "path": tpPath,
813 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700814 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000815 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530816 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000817 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530818 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700819 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530820 "tp-id": TpID,
821 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000822 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530823 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400824 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700825 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400826 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530827 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000828 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530829 log.Fields{
830 "uni": uni,
831 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530832 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530833 }
Gamze Abakafee36392019-10-03 11:17:24 +0000834
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700835 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700836 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700837 if UsMeterID != 0 {
838 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
839 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
840 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000841 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700842 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700843 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700844 "onu-id": onuID,
845 "uni-id": uniID,
846 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700847 "meter-id": UsMeterID,
848 "device-id": f.deviceHandler.device.Id})
849 return 0, nil, nil
850 }
851 }
852 if DsMeterID != 0 {
853 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
854 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
855 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000856 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700857 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700858 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700859 "onu-id": onuID,
860 "uni-id": uniID,
861 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700862 "meter-id": DsMeterID,
863 "device-id": f.deviceHandler.device.Id})
864 return 0, nil, nil
865 }
866 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700867 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700868 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700869 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700870 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700871 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000872
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700873 if tpInstanceExists {
874 return allocID, gemPortIDs, techProfileInstance
875 }
876
877 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700878 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700879 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000880 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700881 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700882 "intf-id": intfID,
883 "onu-id": onuID,
884 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700885 "alloc-ids": allocIDs,
886 "gemports": allgemPortIDs,
887 "device-id": f.deviceHandler.device.Id})
888 // Send Tconts and GEM ports to KV store
889 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530890 return allocID, gemPortIDs, techProfileInstance
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700891 case *openoltpb2.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700892 // CreateSchedulerQueues for EPON needs to be implemented here
893 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700894 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700895 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700896 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700897 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700898 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700899
900 if tpInstanceExists {
901 return allocID, gemPortIDs, techProfileInstance
902 }
903
904 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700905 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700906 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000907 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700908 log.Fields{
909 "alloc-ids": allocIDs,
910 "gemports": allgemPortIDs,
911 "device-id": f.deviceHandler.device.Id})
912 // Send Tconts and GEM ports to KV store
913 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
914 return allocID, gemPortIDs, techProfileInstance
915 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000916 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700917 log.Fields{
918 "tpInst": tpInst})
919 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530920 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530921}
922
npujarec5762e2020-01-01 14:08:48 +0530923func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530924
Neha Sharma96b7bf22020-06-15 10:37:32 +0000925 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530926 log.Fields{
927 "intf-id": intfID,
928 "onu-id": onuID,
929 "uni-id": uniID,
930 "alloc-id": allocID,
931 "gemport-ids": gemPortIDs,
932 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530933 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530934 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000935 logger.Errorw(ctx, "error-while-uploading-allocid-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530936 }
npujarec5762e2020-01-01 14:08:48 +0530937 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000938 logger.Errorw(ctx, "error-while-uploading-gemports-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530939 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700940
Neha Sharma96b7bf22020-06-15 10:37:32 +0000941 logger.Infow(ctx, "stored-tconts-and-gem-into-kv-store-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400942 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530943 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400944 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530945}
946
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700947func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530948 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000949 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700950 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
951 var err error
952 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
953 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
954 if err != nil || f.techprofile == nil {
955 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
956 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
957 }
958 logger.Debugw(ctx, "init-tech-profile-done",
959 log.Fields{
960 "intf-id": intfID,
961 "device-id": f.deviceHandler.device.Id})
962 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700963 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530964 }
965 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700966 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
967 return fmt.Errorf("pon-port-idx-not-found-in-the-device-info-pon-port-range-%v", f.ponPortIdx)
manikkaraj kbf256be2019-03-25 00:13:48 +0530968}
969
Gamze Abaka7650be62021-02-26 10:50:36 +0000970func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
971 flowContext.classifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000972 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530973 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000974 "uplinkClassifier": flowContext.classifier,
975 "uplinkAction": flowContext.action})
976 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530977 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530978}
979
Gamze Abaka7650be62021-02-26 10:50:36 +0000980func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
981 downlinkClassifier := flowContext.classifier
982 downlinkAction := flowContext.action
983
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700984 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000985 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530986 log.Fields{
987 "downlinkClassifier": downlinkClassifier,
988 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400989 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
990 if vlan, exists := downlinkClassifier[VlanVid]; exists {
991 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700992 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700993 if uint32(metadata.(uint64)) == plt.MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000994 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530995 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000996 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +0530997 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +0000998 "onu-id": flowContext.onuID,
999 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001000 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -04001001 }
1002 }
1003 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301004 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001005
Manikkaraj k884c1242019-04-11 16:26:42 +05301006 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001007 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -04001008 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1009 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +05301010 if ok {
1011 downlinkAction[VlanVid] = dlClVid & 0xfff
1012 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05301013 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301014 "reason": "failed-to-convert-vlanid-classifier",
1015 "vlan-id": VlanVid,
1016 "device-id": f.deviceHandler.device.Id}, nil).Log()
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 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001406 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1407 vid := uint32(metadata)
1408 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001409 classifier.IVid = vid
1410 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301411 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301412 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001413 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301414 classifier.OPbits = vlanPcp
1415 } else {
1416 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301417 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001418 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1419 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1420 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1421 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001422 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001423 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1424 classifier.PktTagType = pktTagType
1425
1426 switch pktTagType {
1427 case SingleTag:
1428 case DoubleTag:
1429 case Untagged:
1430 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001431 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301432 }
1433 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001434 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301435}
1436
Gamze Abaka724d0852020-03-18 12:10:24 +00001437func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001438 var actionCmd openoltpb2.ActionCmd
1439 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301440 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001441 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301442 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001443 if _, ok := actionInfo[VlanPcp]; ok {
1444 action.Cmd.RemarkInnerPbits = true
1445 action.IPbits = actionInfo[VlanPcp].(uint32)
1446 if _, ok := actionInfo[VlanVid]; ok {
1447 action.Cmd.TranslateInnerTag = true
1448 action.IVid = actionInfo[VlanVid].(uint32)
1449 }
1450 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001451 } else if _, ok := actionInfo[PushVlan]; ok {
1452 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301453 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001454 if _, ok := actionInfo[VlanPcp]; ok {
1455 action.OPbits = actionInfo[VlanPcp].(uint32)
1456 action.Cmd.RemarkOuterPbits = true
1457 if _, ok := classifierInfo[VlanVid]; ok {
1458 action.IVid = classifierInfo[VlanVid].(uint32)
1459 action.Cmd.TranslateInnerTag = true
1460 }
1461 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001462 } else if _, ok := actionInfo[TrapToHost]; ok {
1463 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301464 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001465 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301466 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001467 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301468}
1469
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001470// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001471func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001472 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301473}
1474
Gamze Abakafee36392019-10-03 11:17:24 +00001475// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001476// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1477// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1478// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1479// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1480// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1481// because it was observed that if the ONU device was deleted too soon after the flows were
1482// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1483// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1484// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001485func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301486 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001487 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1488
Gamze Abakafee36392019-10-03 11:17:24 +00001489 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001490
1491 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001492 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001493 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1494 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
1495 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1496 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1497 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1498 log.Fields{
1499 "tp-id": tpID,
1500 "path": tpPath})
1501 }
1502 switch tpInstance := tpInst.(type) {
1503 case *tp_pb.TechProfileInstance:
1504 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1505 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1506 }
1507 // Force cleanup scheduler/queues -- end
1508
1509 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301510 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001511 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301512 // return err
1513 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001514 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001515 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 +00001516 }
1517 return nil
1518}
1519
1520// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301521func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001522 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001523 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001524 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001525 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301526 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1527 log.Fields{
1528 "tp-id": tpID,
1529 "uni-port-name": uniPortName,
1530 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001531 }
1532 return nil
1533}
1534
David K. Bainbridge794735f2020-02-11 21:01:37 -08001535func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001536
1537 var intfID uint32
1538 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1539 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1540 */
1541 if deviceFlow.AccessIntfId != -1 {
1542 intfID = uint32(deviceFlow.AccessIntfId)
1543 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001544 // We need to log the valid interface ID.
1545 // 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 +00001546 intfID = uint32(deviceFlow.NetworkIntfId)
1547 }
1548
Neha Sharma96b7bf22020-06-15 10:37:32 +00001549 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301550 "flow": *deviceFlow,
1551 "device-id": f.deviceHandler.device.Id,
1552 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001553 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001554
1555 st, _ := status.FromError(err)
1556 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001557 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001558 "err": err,
1559 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301560 "device-id": f.deviceHandler.device.Id,
1561 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001562 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301563 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001564
1565 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001566 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301567 log.Fields{"err": err,
1568 "device-flow": deviceFlow,
1569 "device-id": f.deviceHandler.device.Id,
1570 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001571 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001572 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001573 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301574 log.Fields{
1575 "flow": *deviceFlow,
1576 "device-id": f.deviceHandler.device.Id,
1577 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001578
1579 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1580 if deviceFlow.AccessIntfId != -1 {
1581 // No need to register the flow if it is a trap on nni flow.
1582 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1583 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1584 return err
1585 }
1586 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001587 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001588}
1589
Neha Sharma96b7bf22020-06-15 10:37:32 +00001590func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1591 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301592 log.Fields{
1593 "flow": *deviceFlow,
1594 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001595 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001596 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001597 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001598 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301599 log.Fields{
1600 "err": err,
1601 "deviceFlow": deviceFlow,
1602 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001603 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001604 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001605 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001606 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001607
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001608 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001609 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001610 "of-flow-id": ofFlowID,
1611 "flow": *deviceFlow,
1612 "device-id": f.deviceHandler.device.Id,
1613 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001614 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301615}
1616
David K. Bainbridge794735f2020-02-11 21:01:37 -08001617func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001618
1619 classifierInfo := make(map[string]interface{})
1620 actionInfo := make(map[string]interface{})
1621
1622 classifierInfo[EthType] = uint32(LldpEthType)
1623 classifierInfo[PacketTagType] = Untagged
1624 actionInfo[TrapToHost] = true
1625
1626 // LLDP flow is installed to trap LLDP packets on the NNI port.
1627 // We manage flow_id resource pool on per PON port basis.
1628 // Since this situation is tricky, as a hack, we pass the NNI port
1629 // index (network_intf_id) as PON port Index for the flow_id resource
1630 // pool. Also, there is no ONU Id available for trapping LLDP packets
1631 // on NNI port, use onu_id as -1 (invalid)
1632 // ****************** CAVEAT *******************
1633 // This logic works if the NNI Port Id falls within the same valid
1634 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1635 // we need to have a re-look at this.
1636 // *********************************************
1637
1638 var onuID = -1
1639 var uniID = -1
1640 var gemPortID = -1
1641
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001642 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001643 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301644 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001645 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001646 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001647 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001648 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001649 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001650
David K. Bainbridge794735f2020-02-11 21:01:37 -08001651 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1652 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301653 return olterrors.NewErrInvalidValue(
1654 log.Fields{
1655 "classifier": classifierInfo,
1656 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001657 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001658 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301659 log.Fields{
1660 "classifier": *classifierProto,
1661 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001662 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001663 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301664 return olterrors.NewErrInvalidValue(
1665 log.Fields{
1666 "action": actionInfo,
1667 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001668 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001669 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301670 log.Fields{
1671 "action": *actionProto,
1672 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001673
1674 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1675 OnuId: int32(onuID), // OnuId not required
1676 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001677 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001678 FlowType: Downstream,
1679 NetworkIntfId: int32(networkInterfaceID),
1680 GemportId: int32(gemPortID),
1681 Classifier: classifierProto,
1682 Action: actionProto,
1683 Priority: int32(flow.Priority),
1684 Cookie: flow.Cookie,
1685 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001686 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001687 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301688 log.Fields{
1689 "flow": downstreamflow,
1690 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001691 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001692 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301693 log.Fields{
1694 "device-id": f.deviceHandler.device.Id,
1695 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001696 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001697
David K. Bainbridge794735f2020-02-11 21:01:37 -08001698 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301699}
1700
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001701func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1702 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001703}
1704
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001705//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001706func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001707 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1708 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1709 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001710 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301711 log.Fields{
1712 "intf-id": intfID,
1713 "onu-id": onuID,
1714 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001715 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001716 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301717 return nil, olterrors.NewErrNotFound("onu-child-device",
1718 log.Fields{
1719 "onu-id": onuID,
1720 "intf-id": intfID,
1721 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001722 }
khenaidoo106c61a2021-08-11 18:05:46 -04001723 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 -07001724 //better to ad the device to cache here.
1725 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1726 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001727 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301728 log.Fields{
1729 "intf-id": intfID,
1730 "onu-id": onuID,
1731 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001732 }
1733
1734 return onuDev.(*OnuDevice), nil
1735}
1736
1737//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001738func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1739 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301740 log.Fields{
1741 "pon-port": intfID,
1742 "onu-id": onuID,
1743 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001744 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001745 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001746 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301747 return nil, olterrors.NewErrNotFound("onu",
1748 log.Fields{
1749 "interface-id": parentPortNo,
1750 "onu-id": onuID,
1751 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001752 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301753 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001754 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301755 log.Fields{
1756 "device-id": f.deviceHandler.device.Id,
1757 "child_device_id": onuDevice.Id,
1758 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301759 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301760}
1761
Neha Sharma96b7bf22020-06-15 10:37:32 +00001762func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1763 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301764 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001765 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301766 log.Fields{
1767 "intf-id": intfID,
1768 "onu-id": onuID,
1769 "uni-id": uniID,
1770 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001771 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301772 }
1773
khenaidoo106c61a2021-08-11 18:05:46 -04001774 delGemPortMsg := &ic.DeleteGemPortMessage{
1775 DeviceId: onuDev.deviceID,
1776 UniId: uniID,
1777 TpInstancePath: tpPath,
1778 GemPortId: gemPortID,
1779 }
1780 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1781
1782 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301783 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1784 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001785 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1786 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301787 "onu-id": onuDev.deviceID,
1788 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001789 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301790 }
khenaidoo106c61a2021-08-11 18:05:46 -04001791
Neha Sharma96b7bf22020-06-15 10:37:32 +00001792 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301793 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001794 "msg": delGemPortMsg,
1795 "from-adapter": f.deviceHandler.device.Type,
1796 "to-adapter": onuDev.deviceType,
1797 "device-id": f.deviceHandler.device.Id,
1798 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301799 return nil
1800}
1801
Neha Sharma96b7bf22020-06-15 10:37:32 +00001802func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1803 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301804 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001805 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301806 log.Fields{
1807 "intf-id": intfID,
1808 "onu-id": onuID,
1809 "uni-id": uniID,
1810 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001811 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301812 }
1813
khenaidoo106c61a2021-08-11 18:05:46 -04001814 delTcontMsg := &ic.DeleteTcontMessage{
1815 DeviceId: onuDev.deviceID,
1816 UniId: uniID,
1817 TpInstancePath: tpPath,
1818 AllocId: allocID,
1819 }
1820
Neha Sharma96b7bf22020-06-15 10:37:32 +00001821 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301822 log.Fields{
1823 "msg": *delTcontMsg,
1824 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001825
1826 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301827 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1828 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001829 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1830 "to-adapter": onuDev.adapterEndpoint,
1831 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301832 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001833 "device-id": f.deviceHandler.device.Id}, err)
1834
Girish Gowdra6b130582019-11-20 16:45:20 +05301835 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001836 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301837 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001838 "msg": delTcontMsg,
1839 "device-id": f.deviceHandler.device.Id,
1840 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301841 return nil
1842}
1843
Girish Gowdrac3037402020-01-22 20:29:53 +05301844// Once the gemport is released for a given onu, it also has to be cleared from local cache
1845// which was used for deriving the gemport->logicalPortNo during packet-in.
1846// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1847// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001848func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001849 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301850 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001851 "gem-port-id": gemPortID,
1852 "intf-id": intfID,
1853 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001854 "device-id": f.deviceHandler.device.Id})
1855 f.onuGemInfoLock.RLock()
1856 onugem, ok := f.onuGemInfoMap[onuID]
1857 f.onuGemInfoLock.RUnlock()
1858 if !ok {
1859 logger.Warnw(ctx, "onu gem info already cleared from cache", log.Fields{
1860 "gem-port-id": gemPortID,
1861 "intf-id": intfID,
1862 "onu-id": onuID,
1863 "device-id": f.deviceHandler.device.Id})
1864 return
1865 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001866deleteLoop:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001867 for j, gem := range onugem.GemPorts {
1868 // If the gemport is found, delete it from local cache.
1869 if gem == gemPortID {
1870 onugem.GemPorts = append(onugem.GemPorts[:j], onugem.GemPorts[j+1:]...)
1871 f.onuGemInfoLock.Lock()
1872 f.onuGemInfoMap[onuID] = onugem
1873 f.onuGemInfoLock.Unlock()
1874 logger.Infow(ctx, "removed-gemport-from-local-cache",
1875 log.Fields{
1876 "intf-id": intfID,
1877 "onu-id": onuID,
1878 "deletedgemport-id": gemPortID,
1879 "gemports": onugem.GemPorts,
1880 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001881 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301882 }
1883 }
1884}
1885
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301886//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001887// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001888func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Girish Gowdra82c80982021-03-26 16:22:02 -07001889 gemPortID int32, flowID uint64, portNum uint32, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001890
Girish Gowdraa482f272021-03-24 23:04:19 -07001891 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1892 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001893 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1894 log.Fields{
1895 "tpPath": tpPath,
1896 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001897
1898 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1899
1900 if used {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001901 f.gemToFlowIDsKey.RLock()
1902 flowIDs := f.gemToFlowIDs[uint32(gemPortID)]
1903 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001904
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001905 for i, flowIDinMap := range flowIDs {
1906 if flowIDinMap == flowID {
1907 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001908 f.gemToFlowIDsKey.Lock()
1909 f.gemToFlowIDs[uint32(gemPortID)] = flowIDs
1910 f.gemToFlowIDsKey.Unlock()
1911 // everytime gemToFlowIDs cache is updated the same should be updated
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001912 // in kv store by calling UpdateFlowIDsForGem
Girish Gowdraa482f272021-03-24 23:04:19 -07001913 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001914 return err
1915 }
1916 break
1917 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001918 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001919 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1920 log.Fields{
1921 "gemport-id": gemPortID,
1922 "usedByFlows": flowIDs,
1923 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001924
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001925 return nil
1926 }
1927 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 -07001928 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001929 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), uint32(gemPortID)) // ignore error and proceed.
1930 //everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001931 // by calling DeleteFlowIDsForGem
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001932 f.gemToFlowIDsKey.Lock()
1933 delete(f.gemToFlowIDs, uint32(gemPortID))
1934 f.gemToFlowIDsKey.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001935
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001936 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1937
1938 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001939
Mahir Gunyel199570a2021-07-04 15:39:36 -07001940 //First remove TCONT from child if needed. Then remove the GEM.
1941 //It is expected from child to clean ani side conf if all GEMs of TP are deleted.
1942 //Before this, ensure that the related TCONT deletions are informed to child.
1943 //Refer to VOL-4215.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001944 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001945 if err != nil || techprofileInst == nil {
1946 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1947 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1948 if childDevice == nil {
1949 // happens when subscriber un-provision is immediately followed by child device delete
1950 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1951 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1952 return nil
1953 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001954 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1955 log.Fields{
1956 "tp-id": tpID,
1957 "path": tpPath}, err)
1958 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001959 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001960 case *tp_pb.TechProfileInstance:
Gamze Abakacb0e6772021-06-10 08:32:12 +00001961 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst, uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001962 if !ok {
Girish Gowdraa482f272021-03-24 23:04:19 -07001963 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001964 logger.Warn(ctx, err)
1965 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001966 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001967 logger.Warn(ctx, err)
1968 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001969 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 -07001970 logger.Warn(ctx, err)
1971 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001972 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 -07001973 logger.Warn(ctx, err)
1974 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001975 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001976 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07001977 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001978 logger.Warn(ctx, err)
1979 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001980 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001981 logger.Warn(ctx, err)
1982 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001983 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001984 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001985 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001986 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301987 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07001988 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05301989 "onu-id": onuID,
1990 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001991 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04001992 "alloc-id": techprofileInst.AllocId,
1993 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00001994 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001995 default:
1996 logger.Errorw(ctx, "error-unknown-tech",
1997 log.Fields{
1998 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001999 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002000
Mahir Gunyel199570a2021-07-04 15:39:36 -07002001 // Delete the gem port on the ONU. Send Gem Removal After TCONT removal.
2002 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
2003 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2004 log.Fields{
2005 "err": err,
2006 "intfID": intfID,
2007 "onu-id": onuID,
2008 "uni-id": uniID,
2009 "device-id": f.deviceHandler.device.Id,
2010 "gemport-id": gemPortID})
2011 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302012 return nil
2013}
2014
David K. Bainbridge794735f2020-02-11 21:01:37 -08002015// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002016func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002017 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302018 log.Fields{
2019 "flowDirection": flowDirection,
2020 "flow": *flow,
2021 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002022
2023 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002024 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002025 }
2026
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302027 classifierInfo := make(map[string]interface{})
2028
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002029 portNum, Intf, onu, uni, inPort, ethType, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302030 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002031 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002032 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302033 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302034
David K. Bainbridge794735f2020-02-11 21:01:37 -08002035 onuID := int32(onu)
2036 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002037 tpID, err := getTpIDFromFlow(ctx, flow)
2038 if err != nil {
2039 return olterrors.NewErrNotFound("tp-id",
2040 log.Fields{
2041 "flow": flow,
2042 "intf-id": Intf,
2043 "onu-id": onuID,
2044 "uni-id": uniID,
2045 "device-id": f.deviceHandler.device.Id}, err)
2046 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302047
2048 for _, field := range flows.GetOfbFields(flow) {
2049 if field.Type == flows.IP_PROTO {
2050 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002051 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302052 }
2053 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002054 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302055 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002056 "flow-id": flow.Id,
2057 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302058 "onu-id": onuID,
2059 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302060
2061 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2062 onuID = -1
2063 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002064 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002065 Intf, err = plt.IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002066 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002067 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002068 log.Fields{
2069 "port-number": inPort,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002070 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002071 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002072 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302073 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002074
2075 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2076 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002077 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2078 return err
2079 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002080
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002081 f.flowIDToGemsLock.Lock()
2082 gems, ok := f.flowIDToGems[flow.Id]
2083 if !ok {
2084 logger.Errorw(ctx, "flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id})
2085 f.flowIDToGemsLock.Unlock()
2086 return olterrors.NewErrNotFound("flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id}, nil)
2087 }
2088 copyOfGems := make([]uint32, len(gems))
2089 _ = copy(copyOfGems, gems)
2090 // Delete the flow-id to gemport list entry from the map now the flow is deleted.
2091 delete(f.flowIDToGems, flow.Id)
2092 f.flowIDToGemsLock.Unlock()
2093
2094 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": copyOfGems})
2095 for _, gem := range copyOfGems {
2096 if err = f.clearResources(ctx, Intf, onuID, uniID, int32(gem), flow.Id, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002097 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002098 "flow-id": flow.Id,
2099 "device-id": f.deviceHandler.device.Id,
2100 "onu-id": onuID,
2101 "intf": Intf,
2102 "gem": gem,
2103 "err": err,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002104 })
2105 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302106 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302107 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002108
Girish Gowdra82c80982021-03-26 16:22:02 -07002109 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2110 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2111 return err
2112 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002113 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002114}
2115
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002116//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002117func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002118
Matteo Scandolof16389e2021-05-18 00:47:08 +00002119 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302120 var direction string
2121 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002122
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302123 for _, action := range flows.GetActions(flow) {
2124 if action.Type == flows.OUTPUT {
2125 if out := action.GetOutput(); out != nil {
2126 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002127 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302128 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002129 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002130 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002131 }
2132 }
2133 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002134
2135 if flows.HasGroup(flow) {
2136 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002137 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002138 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302139 direction = Upstream
2140 } else {
2141 direction = Downstream
2142 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302143
Girish Gowdracefae192020-03-19 18:14:10 -07002144 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002145 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002146
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002147 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002148}
2149
Esin Karamanae41e2b2019-12-17 18:13:13 +00002150//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2151func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002152 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002153 if ethType, ok := classifierInfo[EthType]; ok {
2154 if ethType.(uint32) == IPv4EthType {
2155 if ipProto, ok := classifierInfo[IPProto]; ok {
2156 if ipProto.(uint32) == IgmpProto {
2157 return true
2158 }
2159 }
2160 }
2161 }
2162 }
2163 return false
2164}
2165
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002166// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2167func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2168 // Step1 : Fill flowControlBlock
2169 // Step2 : Push the flowControlBlock to ONU channel
2170 // Step3 : Wait on response channel for response
2171 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002172 startTime := time.Now()
2173 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002174 errChan := make(chan error)
2175 flowCb := flowControlBlock{
2176 ctx: ctx,
2177 addFlow: addFlow,
2178 flow: flow,
2179 flowMetadata: flowMetadata,
2180 errChan: &errChan,
2181 }
2182 inPort, outPort := getPorts(flow)
2183 var onuID uint32
2184 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002185 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002186 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002187 if f.flowHandlerRoutineActive[onuID] {
2188 // inPort or outPort is InvalidPort for trap-from-nni flows.
2189 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2190 // Send the flowCb on the ONU flow channel
2191 f.incomingFlows[onuID] <- flowCb
2192 // Wait on the channel for flow handlers return value
2193 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002194 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002195 return err
2196 }
2197 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2198 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002199}
2200
2201// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2202// 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 -07002203func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002204 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002205 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002206 // block on the channel to receive an incoming flow
2207 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002208 case flowCb := <-subscriberFlowChannel:
2209 if flowCb.addFlow {
2210 logger.Info(flowCb.ctx, "adding-flow-start")
2211 startTime := time.Now()
2212 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2213 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2214 // Pass the return value over the return channel
2215 *flowCb.errChan <- err
2216 } else {
2217 logger.Info(flowCb.ctx, "removing-flow-start")
2218 startTime := time.Now()
2219 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2220 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2221 // Pass the return value over the return channel
2222 *flowCb.errChan <- err
2223 }
2224 case <-stopHandler:
2225 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2226 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002227 }
2228 }
2229}
2230
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002231// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
2232func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context) {
2233 for i, v := range f.stopFlowHandlerRoutine {
2234 if f.flowHandlerRoutineActive[i] {
2235 v <- true
2236 }
2237 }
2238 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2239}
2240
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002241// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302242// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002243func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002244 classifierInfo := make(map[string]interface{})
2245 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002246 var UsMeterID uint32
2247 var DsMeterID uint32
2248
Neha Sharma96b7bf22020-06-15 10:37:32 +00002249 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302250 log.Fields{
2251 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002252 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002253 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002254
Neha Sharma96b7bf22020-06-15 10:37:32 +00002255 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002256 if err != nil {
2257 // Error logging is already done in the called function
2258 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002259 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302260 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002261
Esin Karamanccb714b2019-11-29 15:02:06 +00002262 if flows.HasGroup(flow) {
2263 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002264 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002265 }
2266
manikkaraj k17652a72019-05-06 09:06:36 -04002267 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002268 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002269 if err != nil {
2270 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002271 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002272 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002273
Neha Sharma96b7bf22020-06-15 10:37:32 +00002274 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302275 log.Fields{
2276 "classifierinfo_inport": classifierInfo[InPort],
2277 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002278 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002279
Humera Kouser94d7a842019-08-25 19:04:32 -04002280 if ethType, ok := classifierInfo[EthType]; ok {
2281 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002282 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002283 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002284 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002285 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002286 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002287 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2288 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2289 }
2290 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002291 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002292 if ipProto, ok := classifierInfo[IPProto]; ok {
2293 if ipProto.(uint32) == IPProtoDhcp {
2294 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302295 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002296 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002297 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002298 }
2299 }
2300 }
2301 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002302 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002303 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002304 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002305 }
A R Karthick1f85b802019-10-11 05:06:05 +00002306
npujarec5762e2020-01-01 14:08:48 +05302307 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002308 // also update flowmgr cache
2309 f.onuGemInfoLock.Lock()
2310 onugem, ok := f.onuGemInfoMap[onuID]
2311 if ok {
2312 found := false
2313 for _, uni := range onugem.UniPorts {
2314 if uni == portNo {
2315 found = true
2316 break
2317 }
2318 }
2319 if !found {
2320 onugem.UniPorts = append(onugem.UniPorts, portNo)
2321 f.onuGemInfoMap[onuID] = onugem
2322 logger.Infow(ctx, "added uni port to onugem cache", log.Fields{"uni": portNo})
2323 }
2324 }
2325 f.onuGemInfoLock.Unlock()
A R Karthick1f85b802019-10-11 05:06:05 +00002326
Neha Sharma96b7bf22020-06-15 10:37:32 +00002327 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002328 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302329 return olterrors.NewErrNotFound("tpid-for-flow",
2330 log.Fields{
2331 "flow": flow,
2332 "intf-id": IntfID,
2333 "onu-id": onuID,
2334 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002335 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002336 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302337 log.Fields{
2338 "tp-id": TpID,
2339 "intf-id": intfID,
2340 "onu-id": onuID,
2341 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002342 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002343 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002344 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002345 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002346 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002347 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002348
2349 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002350 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002351}
Girish Gowdra3d633032019-12-10 16:37:05 +05302352
Esin Karamanccb714b2019-11-29 15:02:06 +00002353// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002354func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002355 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002356 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302357 "classifier-info": classifierInfo,
2358 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002359
Esin Karaman65409d82020-03-18 10:58:18 +00002360 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002361 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002362 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002363 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002364
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002365 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002366
David K. Bainbridge794735f2020-02-11 21:01:37 -08002367 onuID := NoneOnuID
2368 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002369
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002370 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002371 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002372 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002373 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002374 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2375 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002376 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002377 }
2378 groupID := actionInfo[GroupID].(uint32)
2379 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002380 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002381 FlowType: Multicast,
2382 NetworkIntfId: int32(networkInterfaceID),
2383 GroupId: groupID,
2384 Classifier: classifierProto,
2385 Priority: int32(flow.Priority),
2386 Cookie: flow.Cookie}
2387
Kent Hagermane6ff1012020-07-14 15:07:53 -04002388 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002389 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002390 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002391 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002392 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002393 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002394 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002395 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002396 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002397 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002398 //cached group can be removed now
2399 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002400 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002401 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002402 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002403
David K. Bainbridge794735f2020-02-11 21:01:37 -08002404 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002405}
2406
Esin Karaman65409d82020-03-18 10:58:18 +00002407//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2408func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2409 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002410 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002411 if err != nil {
2412 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2413 }
2414 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002415 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002416
2417 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2418 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002419}
2420
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002421//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002422func (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 -07002423
Neha Sharma96b7bf22020-06-15 10:37:32 +00002424 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302425 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002426 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302427 log.Fields{
2428 "intf-id": intfID,
2429 "onu-id": onuID,
2430 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002431 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302432 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002433 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002434
Neha Sharma96b7bf22020-06-15 10:37:32 +00002435 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
khenaidoo106c61a2021-08-11 18:05:46 -04002436 tpDownloadMsg := &ic.TechProfileDownloadMessage{
2437 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002438 UniId: uniID,
2439 TpInstancePath: tpPath,
khenaidoo106c61a2021-08-11 18:05:46 -04002440 TechTpInstance: &ic.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002441 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002442 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002443
2444 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2445 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302446 return olterrors.NewErrCommunication("send-techprofile-download-request",
2447 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002448 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302449 "to-adapter": onuDev.deviceType,
2450 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002451 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002452 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002453 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302454 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302455}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002456
Girish Gowdra197acc12021-08-16 10:59:45 -07002457//AddOnuInfoToFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2458func (f *OpenOltFlowMgr) AddOnuInfoToFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302459
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002460 f.onuGemInfoLock.RLock()
2461 _, ok := f.onuGemInfoMap[onuID]
2462 f.onuGemInfoLock.RUnlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002463 // If the ONU already exists in onuGemInfo list, nothing to do
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002464 if ok {
2465 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2466 log.Fields{"onuID": onuID,
2467 "serialNum": serialNum})
2468 return nil
Girish Gowdra9602eb42020-09-09 15:50:39 -07002469 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002470
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002471 onuGemInfo := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2472 f.onuGemInfoLock.Lock()
2473 f.onuGemInfoMap[onuID] = &onuGemInfo
2474 f.onuGemInfoLock.Unlock()
2475 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onuID, onuGemInfo); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002476 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302477 }
Girish Gowdra197acc12021-08-16 10:59:45 -07002478 logger.Infow(ctx, "added-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302479 log.Fields{
2480 "intf-id": intfID,
2481 "onu-id": onuID,
2482 "serial-num": serialNum,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002483 "onu": onuGemInfo,
Shrey Baid26912972020-04-16 21:02:31 +05302484 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002485 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002486}
2487
Girish Gowdra197acc12021-08-16 10:59:45 -07002488//RemoveOnuInfoFromFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2489func (f *OpenOltFlowMgr) RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32) error {
2490
2491 f.onuGemInfoLock.Lock()
2492 delete(f.onuGemInfoMap, onuID)
2493 f.onuGemInfoLock.Unlock()
2494
2495 if err := f.resourceMgr.DelOnuGemInfo(ctx, intfID, onuID); err != nil {
2496 return err
2497 }
2498 logger.Infow(ctx, "deleted-onuinfo",
2499 log.Fields{
2500 "intf-id": intfID,
2501 "onu-id": onuID,
2502 "device-id": f.deviceHandler.device.Id})
2503 return nil
2504}
2505
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302506//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302507func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002508
Neha Sharma96b7bf22020-06-15 10:37:32 +00002509 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302510 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002511 "gem-port-id": gemPort,
2512 "intf-id": intfID,
2513 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002514 "device-id": f.deviceHandler.device.Id})
2515 f.onuGemInfoLock.RLock()
2516 onugem, ok := f.onuGemInfoMap[onuID]
2517 f.onuGemInfoLock.RUnlock()
2518 if !ok {
2519 logger.Warnw(ctx, "onu gem info is missing", log.Fields{
2520 "gem-port-id": gemPort,
2521 "intf-id": intfID,
2522 "onu-id": onuID,
2523 "device-id": f.deviceHandler.device.Id})
2524 return
2525 }
2526
2527 if onugem.OnuID == onuID {
2528 // check if gem already exists , else update the cache and kvstore
2529 for _, gem := range onugem.GemPorts {
2530 if gem == gemPort {
2531 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2532 log.Fields{
2533 "gem": gemPort,
2534 "device-id": f.deviceHandler.device.Id})
2535 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302536 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302537 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002538 onugem.GemPorts = append(onugem.GemPorts, gemPort)
2539 f.onuGemInfoLock.Lock()
2540 f.onuGemInfoMap[onuID] = onugem
2541 f.onuGemInfoLock.Unlock()
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002542 logger.Debugw(ctx, "updated onu gem info from cache", log.Fields{"onugem": onugem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002543 } else {
2544 logger.Warnw(ctx, "mismatched onu id", log.Fields{
2545 "gem-port-id": gemPort,
2546 "intf-id": intfID,
2547 "onu-id": onuID,
2548 "device-id": f.deviceHandler.device.Id})
2549 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302550 }
npujarec5762e2020-01-01 14:08:48 +05302551 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302552 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002553 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302554 log.Fields{
2555 "intf-id": intfID,
2556 "onu-id": onuID,
2557 "gemPort": gemPort,
2558 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002559 return
2560 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002561 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302562 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002563 "gem-port-id": gemPort,
2564 "intf-id": intfID,
2565 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002566 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002567}
2568
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002569//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302570func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002571 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002572
2573 if packetIn.IntfType == "pon" {
2574 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002575 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002576 onuID, uniID := packetIn.OnuId, packetIn.UniId
2577 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 +00002578
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002579 if packetIn.PortNo != 0 {
2580 logicalPortNum = packetIn.PortNo
2581 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002582 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002583 }
2584 // 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 +00002585 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002586 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002587 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002588 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002589
2590 if logger.V(log.DebugLevel) {
2591 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2592 log.Fields{
2593 "logical-port-num": logicalPortNum,
2594 "intf-type": packetIn.IntfType,
2595 "packet": hex.EncodeToString(packetIn.Pkt),
2596 })
2597 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002598 return logicalPortNum, nil
2599}
2600
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002601//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002602func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002603 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002604
2605 ctag, priority, err := getCTagFromPacket(ctx, packet)
2606 if err != nil {
2607 return 0, err
2608 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302609
Esin Karaman7fb80c22020-07-16 14:23:33 +00002610 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002611 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002612 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002613 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002614 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302615 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002616 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302617 log.Fields{
2618 "pktinkey": pktInkey,
2619 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002620
2621 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002622 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302623 //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 +00002624 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302625 if err == nil {
2626 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002627 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302628 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002629 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002630 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302631 log.Fields{
2632 "pktinkey": pktInkey,
2633 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302634 return gemPortID, nil
2635 }
2636 }
Shrey Baid26912972020-04-16 21:02:31 +05302637 return uint32(0), olterrors.NewErrNotFound("gem-port",
2638 log.Fields{
2639 "pktinkey": pktInkey,
2640 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002641
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002642}
2643
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002644func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2645 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002646 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002647 classifier[PacketTagType] = DoubleTag
2648 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002649 /* We manage flowId resource pool on per PON port basis.
2650 Since this situation is tricky, as a hack, we pass the NNI port
2651 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002652 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002653 on NNI port, use onu_id as -1 (invalid)
2654 ****************** CAVEAT *******************
2655 This logic works if the NNI Port Id falls within the same valid
2656 range of PON Port Ids. If this doesn't work for some OLT Vendor
2657 we need to have a re-look at this.
2658 *********************************************
2659 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002660 onuID := -1
2661 uniID := -1
2662 gemPortID := -1
2663 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002664 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302665 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302666 return olterrors.NewErrNotFound("nni-intreface-id",
2667 log.Fields{
2668 "classifier": classifier,
2669 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002670 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302671 }
2672
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002673 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002674 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002675 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002676 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002677
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002678 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2679 log.Fields{
2680 "classifier": classifier,
2681 "action": action,
2682 "flowId": logicalFlow.Id,
2683 "intf-id": networkInterfaceID})
2684
David K. Bainbridge794735f2020-02-11 21:01:37 -08002685 classifierProto, err := makeOpenOltClassifierField(classifier)
2686 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002687 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002688 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002689 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002690 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002691 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002692 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002693 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002694 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002695 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2696 OnuId: int32(onuID), // OnuId not required
2697 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002698 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002699 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002700 AllocId: int32(allocID), // AllocId not used
2701 NetworkIntfId: int32(networkInterfaceID),
2702 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002703 Classifier: classifierProto,
2704 Action: actionProto,
2705 Priority: int32(logicalFlow.Priority),
2706 Cookie: logicalFlow.Cookie,
2707 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002708 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002709 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002710 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002711 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002712 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002713}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002714
Esin Karamanae41e2b2019-12-17 18:13:13 +00002715//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2716func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2717 var packetType string
2718 ovid, ivid := false, false
2719 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2720 vid := vlanID & VlanvIDMask
2721 if vid != ReservedVlan {
2722 ovid = true
2723 }
2724 }
2725 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2726 vid := uint32(metadata)
2727 if vid != ReservedVlan {
2728 ivid = true
2729 }
2730 }
2731 if ovid && ivid {
2732 packetType = DoubleTag
2733 } else if !ovid && !ivid {
2734 packetType = Untagged
2735 } else {
2736 packetType = SingleTag
2737 }
2738 return packetType
2739}
2740
2741//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002742func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002743 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002744 action := make(map[string]interface{})
2745 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2746 action[TrapToHost] = true
2747 /* We manage flowId resource pool on per PON port basis.
2748 Since this situation is tricky, as a hack, we pass the NNI port
2749 index (network_intf_id) as PON port Index for the flowId resource
2750 pool. Also, there is no ONU Id available for trapping packets
2751 on NNI port, use onu_id as -1 (invalid)
2752 ****************** CAVEAT *******************
2753 This logic works if the NNI Port Id falls within the same valid
2754 range of PON Port Ids. If this doesn't work for some OLT Vendor
2755 we need to have a re-look at this.
2756 *********************************************
2757 */
2758 onuID := -1
2759 uniID := -1
2760 gemPortID := -1
2761 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002762 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002763 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302764 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002765 "classifier": classifier,
2766 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002767 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002768 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002769 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002770 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002771 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002772 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002773
David K. Bainbridge794735f2020-02-11 21:01:37 -08002774 classifierProto, err := makeOpenOltClassifierField(classifier)
2775 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002776 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002777 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002778 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002779 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002780 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002781 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002782 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002783 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002784 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2785 OnuId: int32(onuID), // OnuId not required
2786 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002787 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002788 FlowType: Downstream,
2789 AllocId: int32(allocID), // AllocId not used
2790 NetworkIntfId: int32(networkInterfaceID),
2791 GemportId: int32(gemPortID), // GemportId not used
2792 Classifier: classifierProto,
2793 Action: actionProto,
2794 Priority: int32(logicalFlow.Priority),
2795 Cookie: logicalFlow.Cookie,
2796 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002797 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002798 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002799 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002800 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002801
David K. Bainbridge794735f2020-02-11 21:01:37 -08002802 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002803}
2804
salmansiddiqui7ac62132019-08-22 03:58:50 +00002805func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2806 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302807 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002808 }
2809 if Dir == tp_pb.Direction_UPSTREAM {
2810 return "upstream", nil
2811 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2812 return "downstream", nil
2813 }
2814 return "", nil
2815}
2816
Kent Hagermane6ff1012020-07-14 15:07:53 -04002817// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302818func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002819 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002820 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002821 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002822 intfID := args[IntfID]
2823 onuID := args[OnuID]
2824 uniID := args[UniID]
2825 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002826 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002827 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002828 gemToAes := make(map[uint32]bool)
2829
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002830 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002831 var direction = tp_pb.Direction_UPSTREAM
2832 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002833 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002834 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002835 attributes = TpInst.UpstreamGemPortAttributeList
2836 } else {
2837 attributes = TpInst.DownstreamGemPortAttributeList
2838 direction = tp_pb.Direction_DOWNSTREAM
2839 }
2840 default:
2841 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2842 return
2843 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002844
2845 if len(gemPorts) == 1 {
2846 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002847 gemPortID = gemPorts[0]
2848 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002849 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2850 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002851 pBitMap := attributes[idx].PbitMap
2852 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2853 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2854 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2855 // this pcp bit traffic.
2856 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2857 if pbitSet == pbit1 {
2858 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2859 pbitToGem[pcp] = gemID
2860 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002861 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002862 }
2863 }
2864 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002865 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2866 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2867 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002868 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002869 }
2870
Gamze Abaka7650be62021-02-26 10:50:36 +00002871 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2872 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2873
salmansiddiqui7ac62132019-08-22 03:58:50 +00002874 if ipProto, ok := classifierInfo[IPProto]; ok {
2875 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002876 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002877 "tp-id": tpID,
2878 "alloc-id": allocID,
2879 "intf-id": intfID,
2880 "onu-id": onuID,
2881 "uni-id": uniID,
2882 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002883 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002884 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002885 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002886 }
2887
Girish Gowdra32625212020-04-29 11:26:35 -07002888 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002889 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302890 log.Fields{
2891 "intf-id": intfID,
2892 "onu-id": onuID,
2893 "uni-id": uniID,
2894 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002895 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002896 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002897 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002898 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002899 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002900 return
2901 }
2902 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002903 if ethType.(uint32) == EapEthType {
2904 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002905 "intf-id": intfID,
2906 "onu-id": onuID,
2907 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002908 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002909 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002910 var vlanID uint32
2911 if val, ok := classifierInfo[VlanVid]; ok {
2912 vlanID = (val.(uint32)) & VlanvIDMask
2913 } else {
2914 vlanID = DefaultMgmtVlan
2915 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002916 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002917 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002918 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002919 } else if ethType.(uint32) == PPPoEDEthType {
2920 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2921 "tp-id": tpID,
2922 "alloc-id": allocID,
2923 "intf-id": intfID,
2924 "onu-id": onuID,
2925 "uni-id": uniID,
2926 })
2927 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002928 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002929 logger.Warn(ctx, err)
2930 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002931 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002932 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002933 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002934 "intf-id": intfID,
2935 "onu-id": onuID,
2936 "uni-id": uniID,
2937 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002938 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002939 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002940 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002941 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002942 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002943 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002944 "intf-id": intfID,
2945 "onu-id": onuID,
2946 "uni-id": uniID,
2947 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002948 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002949 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002950 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002951 }
2952 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002953 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302954 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002955 "intf-id": intfID,
2956 "onu-id": onuID,
2957 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302958 "classifier": classifierInfo,
2959 "action": actionInfo,
2960 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002961 return
2962 }
2963 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002964 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002965 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002966 logger.Warn(ctx, err)
2967 }
2968 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002969}
2970
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002971func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002972 f.gemToFlowIDsKey.RLock()
2973 flowIDList := f.gemToFlowIDs[gemPortID]
2974 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002975 return len(flowIDList) > 1
2976
Gamze Abakafee36392019-10-03 11:17:24 +00002977}
2978
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002979func (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 +05302980 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002981 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2982 for _, currentGemPort := range currentGemPorts {
2983 for _, tpGemPort := range tpGemPorts {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002984 if (currentGemPort == tpGemPort.GemportId) && (currentGemPort != gemPortID) {
Gamze Abakafee36392019-10-03 11:17:24 +00002985 return true, currentGemPort
2986 }
2987 }
2988 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002989 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
2990 return false, 0
2991}
Girish Gowdra54934262019-11-13 14:19:55 +05302992
Gamze Abakacb0e6772021-06-10 08:32:12 +00002993func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002994 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2995 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2996 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 +00002997 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302998 for i := 0; i < len(tpInstances); i++ {
2999 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00003000 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003001 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Gamze Abakacb0e6772021-06-10 08:32:12 +00003002 logger.Debugw(ctx, "alloc-is-in-use",
3003 log.Fields{
3004 "device-id": f.deviceHandler.device.Id,
3005 "intfID": sq.intfID,
3006 "onuID": sq.onuID,
3007 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003008 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00003009 })
3010 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303011 }
3012 }
3013 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003014 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003015}
3016
Neha Sharma96b7bf22020-06-15 10:37:32 +00003017func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003018 for _, field := range flows.GetOfbFields(flow) {
3019 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003020 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003021 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003022 } else if field.Type == flows.ETH_DST {
3023 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003024 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003025 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003026 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003027 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003028 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003029 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003030 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003031 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303032 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003033 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003034 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003035 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003036 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003037 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003038 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003039 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003040 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003041 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003042 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003043 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003044 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003045 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003046 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003047 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003048 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003049 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003050 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003051 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003052 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003053 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003054 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003055 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003056 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003057 return
3058 }
3059 }
3060}
3061
Neha Sharma96b7bf22020-06-15 10:37:32 +00003062func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003063 for _, action := range flows.GetActions(flow) {
3064 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003065 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003066 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003068 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003069 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003070 }
Scott Baker355d1742019-10-24 10:57:52 -07003071 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003072 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003073 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003074 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003075 if out := action.GetPush(); out != nil {
3076 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003077 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003078 } else {
3079 actionInfo[PushVlan] = true
3080 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003081 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303082 log.Fields{
3083 "push-tpid": actionInfo[TPID].(uint32),
3084 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003085 }
3086 }
Scott Baker355d1742019-10-24 10:57:52 -07003087 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003088 if out := action.GetSetField(); out != nil {
3089 if field := out.GetField(); field != nil {
3090 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003091 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003092 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003093 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3094 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003095 }
3096 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003097 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003098 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003099 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003100 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003101 }
3102 }
3103 return nil
3104}
3105
Neha Sharma96b7bf22020-06-15 10:37:32 +00003106func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003107 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003108 fieldtype := ofbField.GetType()
3109 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003110 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3111 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003112 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003113 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003114 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003115 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003116 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3117 pcp := ofbField.GetVlanPcp()
3118 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003119 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003120 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003121 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003122 }
3123 }
3124}
3125
Neha Sharma96b7bf22020-06-15 10:37:32 +00003126func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003127 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003128 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003129 } else {
3130 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003131 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003132 }
3133}
3134
Neha Sharma96b7bf22020-06-15 10:37:32 +00003135func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003136 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003137 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003138 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003139 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003140 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003141 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003142 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303143 log.Fields{
3144 "newinport": classifierInfo[InPort].(uint32),
3145 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003146 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303147 return olterrors.NewErrNotFound("child-in-port",
3148 log.Fields{
3149 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3150 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003151 }
3152 }
3153 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003154 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003155 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003156 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003157 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003158 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003159 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303160 log.Fields{
3161 "newoutport": actionInfo[Output].(uint32),
3162 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003163 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303164 return olterrors.NewErrNotFound("out-port",
3165 log.Fields{
3166 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3167 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003168 }
3169 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003170 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003171 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003172 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003173 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303174 log.Fields{
3175 "newinport": actionInfo[Output].(uint32),
3176 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003177 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303178 return olterrors.NewErrNotFound("nni-port",
3179 log.Fields{
3180 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3181 "in-port": classifierInfo[InPort].(uint32),
3182 "out-port": actionInfo[Output].(uint32),
3183 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003184 }
3185 }
3186 }
3187 return nil
3188}
Gamze Abakafee36392019-10-03 11:17:24 +00003189
Neha Sharma96b7bf22020-06-15 10:37:32 +00003190func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003191 /* Metadata 8 bytes:
3192 Most Significant 2 Bytes = Inner VLAN
3193 Next 2 Bytes = Tech Profile ID(TPID)
3194 Least Significant 4 Bytes = Port ID
3195 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3196 subscriber related flows.
3197 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003198 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003199 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003200 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003201 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003202 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003203 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003204}
3205
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003206func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3207 for _, sliceElement := range slice {
3208 if sliceElement == item {
3209 return slice
3210 }
3211 }
3212 return append(slice, item)
3213}
3214
3215func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003216 for _, sliceElement := range slice {
3217 if sliceElement == item {
3218 return slice
3219 }
3220 }
3221 return append(slice, item)
3222}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303223
3224// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003225func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303226
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003227 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303228 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003229 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003230 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003231 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003232 log.Fields{
3233 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003234 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003235 return uint32(0), err
3236 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003237 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303238 return intfID, nil
3239 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003240 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003241 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003242 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003243 log.Fields{
3244 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003245 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003246 return uint32(0), err
3247 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003248 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303249 return intfID, nil
3250 }
3251 return uint32(0), nil
3252}
3253
3254// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003255func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3256 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3257 if err != nil {
3258 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3259 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3260 return
3261 }
3262 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003263
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003264 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003265 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003266 f.packetInGemPortLock.RUnlock()
3267
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303268 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003269 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003270 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 +05303271 log.Fields{
3272 "pktinkey": pktInkey,
3273 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003274 return
3275 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303276 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003277 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003278 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003279 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003280
npujarec5762e2020-01-01 14:08:48 +05303281 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003282 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 +05303283 log.Fields{
3284 "pktinkey": pktInkey,
3285 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303286}
3287
Esin Karaman7fb80c22020-07-16 14:23:33 +00003288//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3289func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3290 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003291 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003292 return 0, 0, errors.New("invalid packet length")
3293 }
3294 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3295 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3296
3297 var index int8
3298 if outerEthType == 0x8100 {
3299 if innerEthType == 0x8100 {
3300 // q-in-q 802.1ad or 802.1q double tagged packet.
3301 // get the inner vlanId
3302 index = 18
3303 } else {
3304 index = 14
3305 }
3306 priority := (packet[index] >> 5) & 0x7
3307 //13 bits composes vlanId value
3308 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3309 return vlan, priority, nil
3310 }
3311 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3312 return 0, 0, nil
3313}
3314
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003315func (f *OpenOltFlowMgr) loadFlowIDsForGemAndGemIDsForFlow(ctx context.Context) {
3316 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - start")
3317 f.onuGemInfoLock.RLock()
3318 f.gemToFlowIDsKey.Lock()
3319 f.flowIDToGemsLock.Lock()
3320 for _, og := range f.onuGemInfoMap {
3321 for _, gem := range og.GemPorts {
3322 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, f.ponPortIdx, gem)
Gamze Abaka6f345c12021-09-08 01:14:33 +00003323 if err == nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003324 f.gemToFlowIDs[gem] = flowIDs
3325 for _, flowID := range flowIDs {
3326 if _, ok := f.flowIDToGems[flowID]; !ok {
3327 f.flowIDToGems[flowID] = []uint32{gem}
3328 } else {
3329 f.flowIDToGems[flowID] = appendUnique32bit(f.flowIDToGems[flowID], gem)
3330 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303331 }
3332 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303333 }
3334 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003335 f.flowIDToGemsLock.Unlock()
3336 f.gemToFlowIDsKey.Unlock()
3337 f.onuGemInfoLock.RUnlock()
3338 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - end")
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303339}
Esin Karamanccb714b2019-11-29 15:02:06 +00003340
Girish Gowdra9602eb42020-09-09 15:50:39 -07003341//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3342// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003343func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003344 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003345 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3346 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003347 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003348 "flow-id": flow.Id,
3349 "device-id": f.deviceHandler.device.Id})
3350 // Remove from device
3351 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3352 // DKB
3353 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3354 log.Fields{
3355 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003356 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003357 return err
3358 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003359
3360 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003361}
3362
khenaidoo106c61a2021-08-11 18:05:46 -04003363func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ic.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003364 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003365 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003366 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003367 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003368 }
3369
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003370 switch tpInst := tpInst.(type) {
3371 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003372 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
3373 return &ic.TechProfileDownloadMessage{
3374 DeviceId: onuDeviceID,
3375 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003376 TpInstancePath: tpPath,
khenaidoo106c61a2021-08-11 18:05:46 -04003377 TechTpInstance: &ic.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
3378 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003379 case *openoltpb2.EponTechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003380 return &ic.TechProfileDownloadMessage{
3381 DeviceId: onuDeviceID,
3382 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003383 TpInstancePath: tpPath,
khenaidoo106c61a2021-08-11 18:05:46 -04003384 TechTpInstance: &ic.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
3385 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003386 default:
3387 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003388 }
khenaidoo106c61a2021-08-11 18:05:46 -04003389 return &ic.TechProfileDownloadMessage{
3390 DeviceId: onuDeviceID,
3391 UniId: uniID,
3392 TpInstancePath: tpPath,
3393 TechTpInstance: nil,
3394 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003395}
3396
Girish Gowdrabcf98af2021-07-01 08:24:42 -07003397func (f *OpenOltFlowMgr) getOnuGemInfoList(ctx context.Context) []rsrcMgr.OnuGemInfo {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003398 var onuGemInfoLst []rsrcMgr.OnuGemInfo
3399 f.onuGemInfoLock.RLock()
3400 defer f.onuGemInfoLock.RUnlock()
3401 for _, v := range f.onuGemInfoMap {
3402 onuGemInfoLst = append(onuGemInfoLst, *v)
3403 }
3404 return onuGemInfoLst
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003405}