blob: 50c17077ea8d0d526797de15e5f0b5e60088bcfb [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
Matteo Scandolo6056e822019-11-13 14:05:29 -080022 "encoding/hex"
Girish Gowdracefae192020-03-19 18:14:10 -070023 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "fmt"
Gamze Abaka7650be62021-02-26 10:50:36 +000025 "strconv"
serkant.uluderya4aff1862020-09-17 23:35:26 +030026 "strings"
27 "sync"
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070028 "time"
serkant.uluderya4aff1862020-09-17 23:35:26 +030029
khenaidoo106c61a2021-08-11 18:05:46 -040030 "github.com/opencord/voltha-lib-go/v7/pkg/meters"
Mahir Gunyel199570a2021-07-04 15:39:36 -070031
khenaidoo106c61a2021-08-11 18:05:46 -040032 "github.com/opencord/voltha-lib-go/v7/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070034 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040035 tp "github.com/opencord/voltha-lib-go/v7/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080036 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040037 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040038 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040039 ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
40 openoltpb2 "github.com/opencord/voltha-protos/v5/go/openolt"
41 tp_pb "github.com/opencord/voltha-protos/v5/go/tech_profile"
42 "github.com/opencord/voltha-protos/v5/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040043
Thomas Lee S94109f12020-03-03 16:39:29 +053044 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000045 "google.golang.org/grpc/codes"
46 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053047)
48
49const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070050 //IPProtoDhcp flow category
51 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Girish Gowdraa09aeab2020-09-14 16:30:52 -070053 //IgmpProto proto value
54 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070055
56 //EapEthType eapethtype value
57 EapEthType = 0x888e
58 //LldpEthType lldp ethtype value
59 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000060 //IPv4EthType IPv4 ethernet type value
61 IPv4EthType = 0x800
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030062 //PPPoEDEthType PPPoE discovery ethernet type value
63 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070064
Andrea Campanella7acc0b92020-02-14 09:20:49 +010065 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
66 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040067
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068 //DefaultMgmtVlan default vlan value
69 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053070
manikkaraj kbf256be2019-03-25 00:13:48 +053071 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070072
David K. Bainbridge82efc492019-09-04 09:57:11 -070073 //Upstream constant
74 Upstream = "upstream"
75 //Downstream constant
76 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000077 //Multicast constant
78 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070079 //PacketTagType constant
80 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070081 //Untagged constant
82 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070083 //SingleTag constant
84 SingleTag = "single_tag"
85 //DoubleTag constant
86 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053087
88 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089
90 //EthType constant
91 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000092 //EthDst constant
93 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070094 //TPID constant
95 TPID = "tpid"
96 //IPProto constant
97 IPProto = "ip_proto"
98 //InPort constant
99 InPort = "in_port"
100 //VlanVid constant
101 VlanVid = "vlan_vid"
102 //VlanPcp constant
103 VlanPcp = "vlan_pcp"
104
105 //UDPDst constant
106 UDPDst = "udp_dst"
107 //UDPSrc constant
108 UDPSrc = "udp_src"
109 //Ipv4Dst constant
110 Ipv4Dst = "ipv4_dst"
111 //Ipv4Src constant
112 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700113 //Metadata constant
114 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700115 //TunnelID constant
116 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700117 //Output constant
118 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000119 //GroupID constant
120 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700121 // Actions
122
123 //PopVlan constant
124 PopVlan = "pop_vlan"
125 //PushVlan constant
126 PushVlan = "push_vlan"
127 //TrapToHost constant
128 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400129 //MaxMeterBand constant
130 MaxMeterBand = 2
131 //VlanPCPMask contant
132 VlanPCPMask = 0xFF
133 //VlanvIDMask constant
134 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000135 //IntfID constant
136 IntfID = "intfId"
137 //OnuID constant
138 OnuID = "onuId"
139 //UniID constant
140 UniID = "uniId"
141 //PortNo constant
142 PortNo = "portNo"
143 //AllocID constant
144 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000145 //GemID constant
146 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000147
148 //NoneOnuID constant
149 NoneOnuID = -1
150 //NoneUniID constant
151 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700152
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700153 // Max number of flows that can be queued per ONU
154 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530155
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700156 bitMapPrefix = "0b"
157 pbit1 = '1'
158)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400159
Gamze Abakafee36392019-10-03 11:17:24 +0000160type schedQueue struct {
161 direction tp_pb.Direction
162 intfID uint32
163 onuID uint32
164 uniID uint32
165 tpID uint32
166 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700167 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000168 meterID uint32
khenaidoodc2116e2021-10-19 17:33:19 -0400169 flowMetadata *ofp.FlowMetadata
Gamze Abakafee36392019-10-03 11:17:24 +0000170}
171
Gamze Abaka7650be62021-02-26 10:50:36 +0000172type flowContext struct {
173 intfID uint32
174 onuID uint32
175 uniID uint32
176 portNo uint32
177 classifier map[string]interface{}
178 action map[string]interface{}
179 logicalFlow *ofp.OfpFlowStats
180 allocID uint32
181 gemPortID uint32
182 tpID uint32
183 pbitToGem map[uint32]uint32
184 gemToAes map[uint32]bool
185}
186
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700187// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
188// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
189// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
190// flow and processes it serially
191type flowControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400192 ctx context.Context // Flow handler context
193 addFlow bool // if true flow to be added, else removed
194 flow *ofp.OfpFlowStats // Flow message
195 flowMetadata *ofp.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
196 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000197}
198
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700199//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530200type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700201 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700202 techprofile tp.TechProfileIf
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700203 deviceHandler *DeviceHandler
204 grpMgr *OpenOltGroupMgr
205 resourceMgr *rsrcMgr.OpenOltResourceMgr
206
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700207 gemToFlowIDs map[uint32][]uint64 // gem port id to flow ids
208 gemToFlowIDsKey sync.RWMutex // lock to be used to access the gemToFlowIDs map
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700209
210 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
211 packetInGemPortLock sync.RWMutex
212
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700213 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700214 onuGemInfoMap map[uint32]*rsrcMgr.OnuGemInfo //onu, gem and uni info local cache -> map of onuID to OnuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700215 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700216 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700217
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700218 flowIDToGems map[uint64][]uint32
219 flowIDToGemsLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700220
221 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
222 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700223 incomingFlows []chan flowControlBlock
224 stopFlowHandlerRoutine []chan bool
225 flowHandlerRoutineActive []bool
manikkaraj kbf256be2019-03-25 00:13:48 +0530226}
227
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700228//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700229func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000230 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530231 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530232 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530233
manikkaraj kbf256be2019-03-25 00:13:48 +0530234 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700235 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700236 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530237 flowMgr.resourceMgr = rMgr
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700238 if err = flowMgr.populateTechProfileForCurrentPonPort(ctx); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700239 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530240 return nil
241 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700242 flowMgr.gemToFlowIDs = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530243 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700244 flowMgr.flowIDToGems = make(map[uint64][]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700245
246 // Create a slice of buffered channels for handling concurrent flows per ONU.
247 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700248 flowMgr.incomingFlows = make([]chan flowControlBlock, plt.MaxOnusPerPon+1)
249 flowMgr.stopFlowHandlerRoutine = make([]chan bool, plt.MaxOnusPerPon+1)
250 flowMgr.flowHandlerRoutineActive = make([]bool, plt.MaxOnusPerPon+1)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700251 for i := range flowMgr.incomingFlows {
252 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
Girish Gowdraae56c722021-11-22 14:31:11 -0800253 flowMgr.stopFlowHandlerRoutine[i] = make(chan bool)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700254 // Spin up a go routine to handling incoming flows (add/remove).
255 // There will be on go routine per ONU.
256 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700257 flowMgr.flowHandlerRoutineActive[i] = true
258 go flowMgr.perOnuFlowHandlerRoutine(i, flowMgr.incomingFlows[i], flowMgr.stopFlowHandlerRoutine[i])
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700259 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700260 flowMgr.onuGemInfoMap = make(map[uint32]*rsrcMgr.OnuGemInfo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530261 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700262 onuIDStart := flowMgr.deviceHandler.deviceInfo.OnuIdStart
263 onuIDEnd := flowMgr.deviceHandler.deviceInfo.OnuIdEnd
264 for onuID := onuIDStart; onuID <= onuIDEnd; onuID++ {
265 // check for a valid serial number in onuGem as GetOnuGemInfo can return nil error in case of nothing found in the path.
Gamze Abaka6f345c12021-09-08 01:14:33 +0000266 onugem, err := rMgr.GetOnuGemInfo(ctx, ponPortIdx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700267 if err == nil && onugem != nil && onugem.SerialNumber != "" {
268 flowMgr.onuGemInfoMap[onuID] = onugem
269 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530270 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700271
272 //Load flowID list per gem map And gemIDs per flow per interface from the kvstore.
273 flowMgr.loadFlowIDsForGemAndGemIDsForFlow(ctx)
274
Esin Karamanccb714b2019-11-29 15:02:06 +0000275 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700276 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000277 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530278 return &flowMgr
279}
280
Kent Hagermane6ff1012020-07-14 15:07:53 -0400281func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700282 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
283 // Flow is not replicated in this case, we need to register the flow for a single gem-port
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700284 return f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700285 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
286 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
287 for _, gemPort := range deviceFlow.PbitToGemport {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700288 if err := f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700289 return err
290 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700291 }
Gamze Abakafee36392019-10-03 11:17:24 +0000292 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700293 return nil
294}
295
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700296func (f *OpenOltFlowMgr) registerFlowIDForGemAndGemIDForFlow(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
297 // update gem->flows map
298 f.gemToFlowIDsKey.Lock()
299 flowIDList, ok := f.gemToFlowIDs[gemPortID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700300 if !ok {
301 flowIDList = []uint64{flowFromCore.Id}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700302 } else {
303 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700304 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700305 f.gemToFlowIDs[gemPortID] = flowIDList
306 f.gemToFlowIDsKey.Unlock()
307
308 // update flow->gems map
309 f.flowIDToGemsLock.Lock()
310 if _, ok := f.flowIDToGems[flowFromCore.Id]; !ok {
311 f.flowIDToGems[flowFromCore.Id] = []uint32{gemPortID}
312 } else {
313 f.flowIDToGems[flowFromCore.Id] = appendUnique32bit(f.flowIDToGems[flowFromCore.Id], gemPortID)
314 }
315 f.flowIDToGemsLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700316
317 // update the flowids for a gem to the KVstore
318 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400319}
320
Girish Gowdra9602eb42020-09-09 15:50:39 -0700321func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000322 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
khenaidoodc2116e2021-10-19 17:33:19 -0400323 UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000324 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530325 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700326 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530327
Neha Sharma96b7bf22020-06-15 10:37:32 +0000328 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530329 "device-id": f.deviceHandler.device.Id,
330 "intf-id": intfID,
331 "onu-id": onuID,
332 "uni-id": uniID,
333 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700334 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530335 "action": actionInfo,
336 "usmeter-iD": UsMeterID,
337 "dsmeter-iD": DsMeterID,
338 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400339 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
340 // is because the flow is an NNI flow and there would be no onu resources associated with it
341 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400342 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200343 cause := "no-onu-id-for-flow"
344 fields := log.Fields{
345 "onu": onuID,
346 "port-no": portNo,
347 "classifer": classifierInfo,
348 "action": actionInfo,
349 "device-id": f.deviceHandler.device.Id}
350 logger.Errorw(ctx, cause, fields)
351 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530352 }
353
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700354 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000355 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530356 "uni": uni,
357 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530358
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700359 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
360 "device-id": f.deviceHandler.device.Id,
361 "intf-id": intfID,
362 "onu-id": onuID,
363 "uni-id": uniID,
364 "port-no": portNo,
365 "classifier": classifierInfo,
366 "action": actionInfo,
367 "usmeter-id": UsMeterID,
368 "dsmeter-id": DsMeterID,
369 "tp-id": TpID})
370 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
371 if allocID == 0 || gemPorts == nil || TpInst == nil {
372 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
373 return olterrors.NewErrNotFound(
374 "alloc-id-gem-ports-tp-unavailable",
375 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400376 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700377 args := make(map[string]uint32)
378 args[IntfID] = intfID
379 args[OnuID] = onuID
380 args[UniID] = uniID
381 args[PortNo] = portNo
382 args[AllocID] = allocID
383
384 /* Flows can be added specific to gemport if p-bits are received.
385 * If no pbit mentioned then adding flows for all gemports
386 */
Gamze Abaka6d0a64f2021-11-18 08:08:33 +0000387 return f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530388}
389
salmansiddiqui7ac62132019-08-22 03:58:50 +0000390// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530391func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400392
Neha Sharma96b7bf22020-06-15 10:37:32 +0000393 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530394 log.Fields{"dir": sq.direction,
395 "intf-id": sq.intfID,
396 "onu-id": sq.onuID,
397 "uni-id": sq.uniID,
398 "tp-id": sq.tpID,
399 "meter-id": sq.meterID,
400 "tp-inst": sq.tpInst,
401 "flowmetadata": sq.flowMetadata,
402 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400403
Girish Gowdra6071f382021-12-14 12:52:04 +0530404 direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000405 if err != nil {
406 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400407 }
408
409 /* Lets make a simple assumption that if the meter-id is present on the KV store,
410 * then the scheduler and queues configuration is applied on the OLT device
411 * in the given direction.
412 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000413
Manikkaraj kb1d51442019-07-23 10:41:02 -0400414 var SchedCfg *tp_pb.SchedulerConfig
Girish Gowdra6071f382021-12-14 12:52:04 +0530415 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400416 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530417 return olterrors.NewErrNotFound("meter",
418 log.Fields{"intf-id": sq.intfID,
419 "onu-id": sq.onuID,
420 "uni-id": sq.uniID,
421 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400422 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000423
Girish Gowdra6071f382021-12-14 12:52:04 +0530424 // update referernce count and return if the meter was already installed before
425 if meterInfo != nil && meterInfo.MeterID == sq.meterID {
426 logger.Debugw(ctx, "scheduler-already-created-for-direction",
427 log.Fields{"device-id": f.deviceHandler.device.Id, "direction": direction, "meter-id": sq.meterID})
428 return f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400429 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000430
Neha Sharma96b7bf22020-06-15 10:37:32 +0000431 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530432 log.Fields{
433 "meter-id": sq.meterID,
Girish Gowdra6071f382021-12-14 12:52:04 +0530434 "direction": direction,
Shrey Baid26912972020-04-16 21:02:31 +0530435 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000436
Gamze Abakafee36392019-10-03 11:17:24 +0000437 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700438 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Gamze Abakafee36392019-10-03 11:17:24 +0000439 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700440 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Girish Kumar8f73fe02019-12-09 13:19:37 +0000441 }
442
Girish Gowdraa482f272021-03-24 23:04:19 -0700443 found := false
444 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000445 if sq.flowMetadata != nil {
446 for _, meter := range sq.flowMetadata.Meters {
447 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700448 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700449 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 +0000450 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700451 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530452 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700453 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400454 break
455 }
456 }
457 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000458 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400459 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700460 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530461 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800462 "reason": "Could-not-get-meterbands-from-flowMetadata",
463 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530464 "meter-id": sq.meterID,
465 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400466 }
Gamze Abaka01174422021-03-10 06:55:27 +0000467
468 var TrafficShaping *tp_pb.TrafficShapingInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700469 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
Gamze Abaka01174422021-03-10 06:55:27 +0000470 return olterrors.NewErrInvalidValue(log.Fields{
471 "reason": "invalid-meter-config",
472 "meter-id": sq.meterID,
473 "device-id": f.deviceHandler.device.Id}, nil)
474 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400475
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700476 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000477 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700479 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530480 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
481 log.Fields{"intf-id": sq.intfID,
482 "direction": sq.direction,
483 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400484 }
485
salmansiddiqui7ac62132019-08-22 03:58:50 +0000486 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400487 * store the meter id on the KV store, for further reference.
488 */
Girish Gowdra6071f382021-12-14 12:52:04 +0530489 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 +0530490 return olterrors.NewErrAdapter("failed-updating-meter-id",
491 log.Fields{"onu-id": sq.onuID,
492 "meter-id": sq.meterID,
493 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400494 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000495 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Girish Gowdra6071f382021-12-14 12:52:04 +0530496 log.Fields{"direction": direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700497 "meter-info": meterInfo,
498 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400499 return nil
500}
501
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700502func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700503 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000504
505 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530506 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
507 log.Fields{"intf-id": sq.intfID,
508 "direction": sq.direction,
509 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000510 }
511
Gamze Abakacb0e6772021-06-10 08:32:12 +0000512 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
513 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
514 log.Fields{
515 "direction": sq.direction,
516 "TrafficScheds": TrafficSched,
517 "device-id": f.deviceHandler.device.Id,
518 "intfID": sq.intfID,
519 "onuID": sq.onuID,
520 "uniID": sq.uniID})
521 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
522 IntfId: sq.intfID, OnuId: sq.onuID,
523 UniId: sq.uniID, PortNo: sq.uniPort,
524 TrafficScheds: TrafficSched}); err != nil {
525 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
526 }
527 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
528 "direction": sq.direction,
529 "traffic-queues": trafficQueues,
530 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000531 }
532
533 // On receiving the CreateTrafficQueues request, the driver should create corresponding
534 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000535 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530536 log.Fields{"direction": sq.direction,
537 "traffic-queues": trafficQueues,
538 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000539 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
540 UniId: sq.uniID, PortNo: sq.uniPort,
541 TrafficQueues: trafficQueues,
542 TechProfileId: TrafficSched[0].TechProfileId}
543 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
544 if len(queues.TrafficQueues) > 1 {
545 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
546 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
547 }
548 f.revertScheduler(ctx, sq, TrafficSched)
Shrey Baid26912972020-04-16 21:02:31 +0530549 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000550 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000551 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530552 "direction": sq.direction,
553 "traffic-queues": trafficQueues,
554 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000555
Esin Karamanccb714b2019-11-29 15:02:06 +0000556 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700557 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000558 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700559 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 +0000560 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
561 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000562 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000563 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700564 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000565 gemPortID: multicastQueuePerPonPort.GemportId,
566 servicePriority: multicastQueuePerPonPort.Priority,
567 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700568 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000569 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400570 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700571 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400572 return err
573 }
Shrey Baid26912972020-04-16 21:02:31 +0530574
Neha Sharma96b7bf22020-06-15 10:37:32 +0000575 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000576 }
577 }
578 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000579 return nil
580}
581
salmansiddiqui7ac62132019-08-22 03:58:50 +0000582// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530583func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400584
585 var Direction string
586 var SchedCfg *tp_pb.SchedulerConfig
587 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000588 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530589 log.Fields{
590 "direction": sq.direction,
591 "intf-id": sq.intfID,
592 "onu-id": sq.onuID,
593 "uni-id": sq.uniID,
594 "uni-port": sq.uniPort,
595 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000596 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700597 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400598 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000599 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700600 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400601 Direction = "downstream"
602 }
603
Girish Gowdraa482f272021-03-24 23:04:19 -0700604 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 -0400605
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700606 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000607 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000608
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700609 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000610 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530611 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
612 log.Fields{
613 "intf-id": sq.intfID,
614 "direction": sq.direction,
615 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000616 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400617
npujarec5762e2020-01-01 14:08:48 +0530618 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000619 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
620 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000621 TrafficQueues: TrafficQueues,
622 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000623 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530624 log.Fields{
625 "intf-id": sq.intfID,
626 "traffic-queues": TrafficQueues,
627 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400628 }
Gamze Abakacb0e6772021-06-10 08:32:12 +0000629 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400630
Gamze Abakacb0e6772021-06-10 08:32:12 +0000631 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
632 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
633 IntfId: sq.intfID, OnuId: sq.onuID,
634 UniId: sq.uniID, PortNo: sq.uniPort,
635 TrafficScheds: TrafficSched}); err != nil {
636 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
637 log.Fields{
638 "intf-id": sq.intfID,
639 "traffic-schedulers": TrafficSched,
640 "onu-id": sq.onuID,
641 "uni-id": sq.uniID,
642 "uni-port": sq.uniPort}, err)
643 }
644
645 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
646 log.Fields{"device-id": f.deviceHandler.device.Id,
647 "intf-id": sq.intfID,
648 "onu-id": sq.onuID,
649 "uni-id": sq.uniID,
650 "uni-port": sq.uniPort})
651
652 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700653 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
Gamze Abakacb0e6772021-06-10 08:32:12 +0000654 // Delete the TCONT on the ONU.
655 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
656 tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
657 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
658 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
659 log.Fields{
660 "intf": sq.intfID,
661 "onu-id": sq.onuID,
662 "uni-id": sq.uniID,
663 "device-id": f.deviceHandler.device.Id,
664 "alloc-id": allocID})
665 }
666 }
667 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000668
669 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400670 * delete the meter id on the KV store.
671 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700672 err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400673 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530674 return olterrors.NewErrAdapter("unable-to-remove-meter",
675 log.Fields{
676 "onu": sq.onuID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700677 "device-id": f.deviceHandler.device.Id,
678 "intf-id": sq.intfID,
679 "onu-id": sq.onuID,
680 "uni-id": sq.uniID,
681 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400682 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000683 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530684 log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530685 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700686 "device-id": f.deviceHandler.device.Id,
687 "intf-id": sq.intfID,
688 "onu-id": sq.onuID,
689 "uni-id": sq.uniID,
690 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400691 return err
692}
693
Girish Gowdra197acc12021-08-16 10:59:45 -0700694// We are trying to force remove the schedulers and queues here if one exists for the given key.
695// We ignore any errors encountered in the process. The errors most likely are encountered when
696// the schedulers and queues are already cleared for the given key.
697func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
698
699 var schedCfg *tp_pb.SchedulerConfig
700 var err error
701 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
702 log.Fields{
703 "direction": sq.direction,
704 "intf-id": sq.intfID,
705 "onu-id": sq.onuID,
706 "uni-id": sq.uniID,
707 "uni-port": sq.uniPort,
708 "tp-id": sq.tpID,
709 "device-id": f.deviceHandler.device.Id})
710 if sq.direction == tp_pb.Direction_UPSTREAM {
711 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
712 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
713 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
714 }
715
716 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
717 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
718 TrafficSched[0].TechProfileId = sq.tpID
719
720 // Remove traffic queues. Ignore any errors, just log them.
721 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
722 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
723 "direction": sq.direction,
724 "intf-id": sq.intfID,
725 "onu-id": sq.onuID,
726 "uni-id": sq.uniID,
727 "uni-port": sq.uniPort,
728 "tp-id": sq.tpID,
729 "device-id": f.deviceHandler.device.Id,
730 "err": err})
731 } else {
732 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
733 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
734 UniId: sq.uniID, PortNo: sq.uniPort,
735 TrafficQueues: TrafficQueues,
736 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
737 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
738 "direction": sq.direction,
739 "intf-id": sq.intfID,
740 "onu-id": sq.onuID,
741 "uni-id": sq.uniID,
742 "uni-port": sq.uniPort,
743 "tp-id": sq.tpID,
744 "device-id": f.deviceHandler.device.Id,
745 "err": err})
746
747 } else {
748 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
749 "direction": sq.direction,
750 "intf-id": sq.intfID,
751 "onu-id": sq.onuID,
752 "uni-id": sq.uniID,
753 "uni-port": sq.uniPort,
754 "tp-id": sq.tpID})
755 }
756 }
757
758 // Remove traffic schedulers. Ignore any errors, just log them.
759 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
760 IntfId: sq.intfID, OnuId: sq.onuID,
761 UniId: sq.uniID, PortNo: sq.uniPort,
762 TrafficScheds: TrafficSched}); err != nil {
763 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
764 "direction": sq.direction,
765 "intf-id": sq.intfID,
766 "onu-id": sq.onuID,
767 "uni-id": sq.uniID,
768 "uni-port": sq.uniPort,
769 "tp-id": sq.tpID,
770 "device-id": f.deviceHandler.device.Id,
771 "err": err})
772 } else {
773 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
774 "direction": sq.direction,
775 "intf-id": sq.intfID,
776 "onu-id": sq.onuID,
777 "uni-id": sq.uniID,
778 "uni-port": sq.uniPort,
779 "tp-id": sq.tpID})
780 }
781}
782
Gamze Abakafee36392019-10-03 11:17:24 +0000783// This function allocates tconts and GEM ports for an ONU
khenaidoodc2116e2021-10-19 17:33:19 -0400784func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) (uint32, []uint32, interface{}) {
Gamze Abakafee36392019-10-03 11:17:24 +0000785 var allocIDs []uint32
786 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530787 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530788 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000789 var err error
npujarec5762e2020-01-01 14:08:48 +0530790 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
791 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000792 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530793
Neha Sharma96b7bf22020-06-15 10:37:32 +0000794 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530795 "intf-id": intfID,
796 "onu-id": onuID,
797 "uni-id": uniID,
798 "device-id": f.deviceHandler.device.Id,
799 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530800
Manikkaraj kb1d51442019-07-23 10:41:02 -0400801 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700802 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000803 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000804 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530805 log.Fields{
806 "path": tpPath,
807 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700808 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000809 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530810 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000811 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530812 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700813 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530814 "tp-id": TpID,
815 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000816 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530817 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400818 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700819 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400820 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530821 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000822 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530823 log.Fields{
824 "uni": uni,
825 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530826 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530827 }
Gamze Abakafee36392019-10-03 11:17:24 +0000828
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700829 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700830 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700831 if UsMeterID != 0 {
832 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
833 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
834 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000835 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700836 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700837 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700838 "onu-id": onuID,
839 "uni-id": uniID,
840 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700841 "meter-id": UsMeterID,
842 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000843 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700844 return 0, nil, nil
845 }
846 }
847 if DsMeterID != 0 {
848 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
849 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
850 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000851 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700852 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700853 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700854 "onu-id": onuID,
855 "uni-id": uniID,
856 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700857 "meter-id": DsMeterID,
858 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000859 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700860 return 0, nil, nil
861 }
862 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700863 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700864 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700865 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700866 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700867 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000868
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700869 if tpInstanceExists {
870 return allocID, gemPortIDs, techProfileInstance
871 }
872
873 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700874 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700875 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000876 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700877 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700878 "intf-id": intfID,
879 "onu-id": onuID,
880 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700881 "alloc-ids": allocIDs,
882 "gemports": allgemPortIDs,
883 "device-id": f.deviceHandler.device.Id})
884 // Send Tconts and GEM ports to KV store
885 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530886 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400887 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700888 // CreateSchedulerQueues for EPON needs to be implemented here
889 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700890 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700891 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700892 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700893 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700894 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700895
896 if tpInstanceExists {
897 return allocID, gemPortIDs, techProfileInstance
898 }
899
900 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700901 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700902 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000903 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700904 log.Fields{
905 "alloc-ids": allocIDs,
906 "gemports": allgemPortIDs,
907 "device-id": f.deviceHandler.device.Id})
908 // Send Tconts and GEM ports to KV store
909 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
910 return allocID, gemPortIDs, techProfileInstance
911 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000912 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700913 log.Fields{
914 "tpInst": tpInst})
915 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530916 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530917}
918
npujarec5762e2020-01-01 14:08:48 +0530919func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530920
Neha Sharma96b7bf22020-06-15 10:37:32 +0000921 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530922 log.Fields{
923 "intf-id": intfID,
924 "onu-id": onuID,
925 "uni-id": uniID,
926 "alloc-id": allocID,
927 "gemport-ids": gemPortIDs,
928 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530929 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530930 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000931 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 +0530932 }
npujarec5762e2020-01-01 14:08:48 +0530933 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000934 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 +0530935 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700936
Neha Sharma96b7bf22020-06-15 10:37:32 +0000937 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 -0400938 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530939 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400940 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530941}
942
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700943func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530944 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000945 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700946 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
947 var err error
948 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
949 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
950 if err != nil || f.techprofile == nil {
951 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
952 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
953 }
954 logger.Debugw(ctx, "init-tech-profile-done",
955 log.Fields{
956 "intf-id": intfID,
957 "device-id": f.deviceHandler.device.Id})
958 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700959 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530960 }
961 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700962 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
963 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 +0530964}
965
Gamze Abaka7650be62021-02-26 10:50:36 +0000966func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Andrea Campanellafaa42152021-10-28 11:50:56 +0530967 flowContext.classifier[PacketTagType] = SingleTag // FIXME: This hardcoding needs to be removed.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000968 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530969 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000970 "uplinkClassifier": flowContext.classifier,
971 "uplinkAction": flowContext.action})
972 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530973 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530974}
975
Gamze Abaka7650be62021-02-26 10:50:36 +0000976func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
977 downlinkClassifier := flowContext.classifier
978 downlinkAction := flowContext.action
979
Andrea Campanellafaa42152021-10-28 11:50:56 +0530980 // TODO: For now mark the PacketTagType as SingleTag when OLT is transparent to VLAN
981 // Per some deployment models, it is also possible that ONU operates on double tagged packets,
982 // so this hardcoding of SingeTag packet-tag-type may be problem for such deployment models.
983 // Need a better way for detection of packet tag type from OpenFlow message.
984 if _, ok := downlinkClassifier[VlanVid]; !ok {
985 downlinkClassifier[PacketTagType] = SingleTag
986 } else {
987 downlinkClassifier[PacketTagType] = DoubleTag
988 downlinkAction[PopVlan] = true
989 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000990 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530991 log.Fields{
992 "downlinkClassifier": downlinkClassifier,
993 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400994 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
995 if vlan, exists := downlinkClassifier[VlanVid]; exists {
996 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700997 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700998 if uint32(metadata.(uint64)) == plt.MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000999 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301000 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001001 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301002 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +00001003 "onu-id": flowContext.onuID,
1004 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001005 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -04001006 }
1007 }
1008 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301009 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001010
Matt Jeannereted16b7c2019-11-01 13:31:35 -04001011 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1012 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +05301013 if ok {
1014 downlinkAction[VlanVid] = dlClVid & 0xfff
Girish Gowdra26f344b2019-10-23 14:39:13 +05301015 }
1016
Gamze Abaka7650be62021-02-26 10:50:36 +00001017 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301018}
1019
Gamze Abaka7650be62021-02-26 10:50:36 +00001020func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001021
Gamze Abaka7650be62021-02-26 10:50:36 +00001022 intfID := flowContext.intfID
1023 onuID := flowContext.onuID
1024 uniID := flowContext.uniID
1025 classifier := flowContext.classifier
1026 action := flowContext.action
1027 allocID := flowContext.allocID
1028 gemPortID := flowContext.gemPortID
1029 tpID := flowContext.tpID
1030 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001031 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301032 log.Fields{
1033 "intf-id": intfID,
1034 "onu-id": onuID,
1035 "uni-id": uniID,
1036 "device-id": f.deviceHandler.device.Id,
1037 "classifier": classifier,
1038 "action": action,
1039 "direction": direction,
1040 "alloc-id": allocID,
1041 "gemport-id": gemPortID,
1042 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001043
1044 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001045 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301046 log.Fields{
1047 "device-id": f.deviceHandler.device.Id,
1048 "intf-id": intfID,
1049 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001050 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301051 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001052 classifierProto, err := makeOpenOltClassifierField(classifier)
1053 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301054 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301055 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001056 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301057 log.Fields{
1058 "classifier": *classifierProto,
1059 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001060 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001061 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301062 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301063 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001064 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301065 log.Fields{
1066 "action": *actionProto,
1067 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001068 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301069 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301070 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001071 log.Fields{
1072 "classifier": classifier,
1073 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301074 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001075 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301076 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001077
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001078 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001079 OnuId: int32(onuID),
1080 UniId: int32(uniID),
1081 FlowId: logicalFlow.Id,
1082 FlowType: direction,
1083 AllocId: int32(allocID),
1084 NetworkIntfId: int32(networkIntfID),
1085 GemportId: int32(gemPortID),
1086 Classifier: classifierProto,
1087 Action: actionProto,
1088 Priority: int32(logicalFlow.Priority),
1089 Cookie: logicalFlow.Cookie,
1090 PortNo: flowContext.portNo,
1091 TechProfileId: tpID,
1092 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1093 PbitToGemport: flowContext.pbitToGem,
1094 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001095 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001096 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001097 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301098 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001099 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301100 log.Fields{"direction": direction,
1101 "device-id": f.deviceHandler.device.Id,
1102 "flow": flow,
1103 "intf-id": intfID,
1104 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001105
David K. Bainbridge794735f2020-02-11 21:01:37 -08001106 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301107}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001108
Gamze Abaka7650be62021-02-26 10:50:36 +00001109func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1110
1111 intfID := flowContext.intfID
1112 onuID := flowContext.onuID
1113 uniID := flowContext.uniID
1114 logicalFlow := flowContext.logicalFlow
1115 classifier := flowContext.classifier
1116 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301117
Neha Sharma96b7bf22020-06-15 10:37:32 +00001118 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301119 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301120 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001121 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301122 "action": action,
1123 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001124 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301125 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301126
1127 // Clear the action map
1128 for k := range action {
1129 delete(action, k)
1130 }
1131
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001132 action[TrapToHost] = true
1133 classifier[UDPSrc] = uint32(68)
1134 classifier[UDPDst] = uint32(67)
1135 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301136
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001137 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001138 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301139 log.Fields{
1140 "device-id": f.deviceHandler.device.Id,
1141 "intf-id": intfID,
1142 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001143 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301144 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301145
Neha Sharma96b7bf22020-06-15 10:37:32 +00001146 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301147 log.Fields{
1148 "ul_classifier": classifier,
1149 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001150 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301151 "intf-id": intfID,
1152 "onu-id": onuID,
1153 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301154
David K. Bainbridge794735f2020-02-11 21:01:37 -08001155 classifierProto, err := makeOpenOltClassifierField(classifier)
1156 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301157 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301158 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001159 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001160 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001161 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301162 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301163 }
1164
David K. Bainbridge794735f2020-02-11 21:01:37 -08001165 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001166 OnuId: int32(onuID),
1167 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001168 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001169 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001170 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001171 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001172 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301173 Classifier: classifierProto,
1174 Action: actionProto,
1175 Priority: int32(logicalFlow.Priority),
1176 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001177 PortNo: flowContext.portNo,
1178 TechProfileId: flowContext.tpID,
1179 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1180 PbitToGemport: flowContext.pbitToGem,
1181 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001182 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001183 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001184 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001185 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001186 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301187 log.Fields{
1188 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001189 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301190 "intf-id": intfID,
1191 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301192
David K. Bainbridge794735f2020-02-11 21:01:37 -08001193 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301194}
1195
Esin Karamanae41e2b2019-12-17 18:13:13 +00001196//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001197func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1198 delete(flowContext.classifier, VlanVid)
1199 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001200}
1201
1202//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001203func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1204
1205 intfID := flowContext.intfID
1206 onuID := flowContext.onuID
1207 uniID := flowContext.uniID
1208 logicalFlow := flowContext.logicalFlow
1209 classifier := flowContext.classifier
1210 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001211
Neha Sharma96b7bf22020-06-15 10:37:32 +00001212 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001213 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301214 return olterrors.NewErrNotFound("nni-interface-id",
1215 log.Fields{
1216 "classifier": classifier,
1217 "action": action,
1218 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001219 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001220 }
1221
1222 // Clear the action map
1223 for k := range action {
1224 delete(action, k)
1225 }
1226
1227 action[TrapToHost] = true
1228 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001229
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001230 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001231 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001232 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001233 }
1234
Neha Sharma96b7bf22020-06-15 10:37:32 +00001235 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301236 log.Fields{
1237 "ul_classifier": classifier,
1238 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001239 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301240 "device-id": f.deviceHandler.device.Id,
1241 "intf-id": intfID,
1242 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001243
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 classifierProto, err := makeOpenOltClassifierField(classifier)
1245 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301246 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001247 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001248 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301249 log.Fields{
1250 "classifier": *classifierProto,
1251 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001252 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001253 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301254 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001255 }
1256
David K. Bainbridge794735f2020-02-11 21:01:37 -08001257 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001258 OnuId: int32(onuID),
1259 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001260 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001261 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001262 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001263 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001264 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001265 Classifier: classifierProto,
1266 Action: actionProto,
1267 Priority: int32(logicalFlow.Priority),
1268 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001269 PortNo: flowContext.portNo,
1270 TechProfileId: flowContext.tpID,
1271 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1272 PbitToGemport: flowContext.pbitToGem,
1273 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001274 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001275
David K. Bainbridge794735f2020-02-11 21:01:37 -08001276 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001277 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 -08001278 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001279
David K. Bainbridge794735f2020-02-11 21:01:37 -08001280 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001281}
1282
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001283// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001284func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1285 intfID := flowContext.intfID
1286 onuID := flowContext.onuID
1287 uniID := flowContext.uniID
1288 portNo := flowContext.portNo
1289 allocID := flowContext.allocID
1290 gemPortID := flowContext.gemPortID
1291 logicalFlow := flowContext.logicalFlow
1292 classifier := flowContext.classifier
1293 action := flowContext.action
1294
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001295 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301296 log.Fields{
1297 "intf-id": intfID,
1298 "onu-id": onuID,
1299 "port-no": portNo,
1300 "alloc-id": allocID,
1301 "gemport-id": gemPortID,
1302 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001303 "flow": logicalFlow,
1304 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301305
1306 uplinkClassifier := make(map[string]interface{})
1307 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301308
manikkaraj kbf256be2019-03-25 00:13:48 +05301309 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001310 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001311 uplinkClassifier[PacketTagType] = SingleTag
1312 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001313 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301314 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001315 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001316 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001317 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301318 "device-id": f.deviceHandler.device.Id,
1319 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001320 "intf-id": intfID,
1321 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001322 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301323 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001324 //Add Uplink EthType Flow
1325 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301326 log.Fields{
1327 "ul_classifier": uplinkClassifier,
1328 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001329 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301330 "device-id": f.deviceHandler.device.Id,
1331 "intf-id": intfID,
1332 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301333
David K. Bainbridge794735f2020-02-11 21:01:37 -08001334 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1335 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301336 return olterrors.NewErrInvalidValue(log.Fields{
1337 "classifier": uplinkClassifier,
1338 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301339 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001340 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301341 log.Fields{
1342 "classifier": *classifierProto,
1343 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001344 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001345 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301346 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301347 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001348 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301349 log.Fields{
1350 "action": *actionProto,
1351 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001352 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301353 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301354 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001355 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301356 "action": action,
1357 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001358 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301359 }
1360
David K. Bainbridge794735f2020-02-11 21:01:37 -08001361 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001362 OnuId: int32(onuID),
1363 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001364 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001365 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001366 AllocId: int32(allocID),
1367 NetworkIntfId: int32(networkIntfID),
1368 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301369 Classifier: classifierProto,
1370 Action: actionProto,
1371 Priority: int32(logicalFlow.Priority),
1372 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001373 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001374 TechProfileId: flowContext.tpID,
1375 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1376 PbitToGemport: flowContext.pbitToGem,
1377 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001378 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001379 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001380 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001381 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001382 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301383 log.Fields{
1384 "device-id": f.deviceHandler.device.Id,
1385 "onu-id": onuID,
1386 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001387 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301388 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001389
David K. Bainbridge794735f2020-02-11 21:01:37 -08001390 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301391}
1392
David K. Bainbridge794735f2020-02-11 21:01:37 -08001393func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001394 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001395
1396 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1397 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1398 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001399 if vlanID != ReservedVlan {
1400 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001401 classifier.OVid = vid
1402 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301403 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301404 // The classifierInfo[Metadata] carries the vlan that the OLT see when it receives packet from the ONU
David K. Bainbridge82efc492019-09-04 09:57:11 -07001405 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1406 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301407 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1408 // If OLT is using transparent tag mechanism, then it classifies whatever tag it sees to/from ONU which
1409 //is OVid from the perspective of the OLT. When OLT also places or pops the outer tag, then classifierInfo[Metadata]
1410 // becomes the IVid.
1411 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1412 if vid != ReservedVlan {
1413 classifier.IVid = vid
1414 }
1415 } else {
1416 if vid != ReservedVlan {
1417 classifier.OVid = vid
1418 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001419 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301420 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301421 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001422 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301423 classifier.OPbits = vlanPcp
1424 } else {
1425 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301426 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001427 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1428 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1429 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1430 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001431 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001432 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1433 classifier.PktTagType = pktTagType
1434
1435 switch pktTagType {
1436 case SingleTag:
1437 case DoubleTag:
1438 case Untagged:
1439 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001440 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301441 }
1442 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001443 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301444}
1445
Gamze Abaka724d0852020-03-18 12:10:24 +00001446func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001447 var actionCmd openoltpb2.ActionCmd
1448 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301449 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001450 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301451 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001452 if _, ok := actionInfo[VlanPcp]; ok {
1453 action.Cmd.RemarkInnerPbits = true
1454 action.IPbits = actionInfo[VlanPcp].(uint32)
1455 if _, ok := actionInfo[VlanVid]; ok {
1456 action.Cmd.TranslateInnerTag = true
1457 action.IVid = actionInfo[VlanVid].(uint32)
1458 }
1459 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001460 } else if _, ok := actionInfo[PushVlan]; ok {
1461 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301462 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001463 if _, ok := actionInfo[VlanPcp]; ok {
1464 action.OPbits = actionInfo[VlanPcp].(uint32)
1465 action.Cmd.RemarkOuterPbits = true
1466 if _, ok := classifierInfo[VlanVid]; ok {
1467 action.IVid = classifierInfo[VlanVid].(uint32)
1468 action.Cmd.TranslateInnerTag = true
1469 }
1470 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001471 } else if _, ok := actionInfo[TrapToHost]; ok {
1472 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301473 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301474 // When OLT is transparent to vlans no-action is valid.
1475 /*
1476 else {
1477 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1478 }
1479 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001480 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301481}
1482
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001483// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001484func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001485 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301486}
1487
Gamze Abakafee36392019-10-03 11:17:24 +00001488// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001489// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1490// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1491// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1492// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1493// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1494// because it was observed that if the ONU device was deleted too soon after the flows were
1495// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1496// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1497// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001498func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301499 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001500 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1501
Gamze Abakafee36392019-10-03 11:17:24 +00001502 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001503
1504 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001505 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001506 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1507 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
1508 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1509 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1510 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1511 log.Fields{
1512 "tp-id": tpID,
1513 "path": tpPath})
1514 }
1515 switch tpInstance := tpInst.(type) {
1516 case *tp_pb.TechProfileInstance:
1517 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1518 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1519 }
1520 // Force cleanup scheduler/queues -- end
1521
1522 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301523 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001524 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301525 // return err
1526 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001527 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001528 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 +00001529 }
1530 return nil
1531}
1532
1533// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301534func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001535 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001536 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001537 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001538 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301539 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1540 log.Fields{
1541 "tp-id": tpID,
1542 "uni-port-name": uniPortName,
1543 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001544 }
1545 return nil
1546}
1547
David K. Bainbridge794735f2020-02-11 21:01:37 -08001548func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001549
1550 var intfID uint32
1551 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1552 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1553 */
1554 if deviceFlow.AccessIntfId != -1 {
1555 intfID = uint32(deviceFlow.AccessIntfId)
1556 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001557 // We need to log the valid interface ID.
1558 // 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 +00001559 intfID = uint32(deviceFlow.NetworkIntfId)
1560 }
1561
Neha Sharma96b7bf22020-06-15 10:37:32 +00001562 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301563 "flow": *deviceFlow,
1564 "device-id": f.deviceHandler.device.Id,
1565 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001566 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001567
1568 st, _ := status.FromError(err)
1569 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001570 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001571 "err": err,
1572 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301573 "device-id": f.deviceHandler.device.Id,
1574 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001575 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301576 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001577
1578 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001579 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301580 log.Fields{"err": err,
1581 "device-flow": deviceFlow,
1582 "device-id": f.deviceHandler.device.Id,
1583 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001584 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001585 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001586 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301587 log.Fields{
1588 "flow": *deviceFlow,
1589 "device-id": f.deviceHandler.device.Id,
1590 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001591
1592 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1593 if deviceFlow.AccessIntfId != -1 {
1594 // No need to register the flow if it is a trap on nni flow.
1595 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1596 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1597 return err
1598 }
1599 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001600 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001601}
1602
Neha Sharma96b7bf22020-06-15 10:37:32 +00001603func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1604 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301605 log.Fields{
1606 "flow": *deviceFlow,
1607 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001608 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001609 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001610 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001611 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301612 log.Fields{
1613 "err": err,
1614 "deviceFlow": deviceFlow,
1615 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001616 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001617 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001618 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001619 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001620
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001621 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001622 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001623 "of-flow-id": ofFlowID,
1624 "flow": *deviceFlow,
1625 "device-id": f.deviceHandler.device.Id,
1626 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001627 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301628}
1629
David K. Bainbridge794735f2020-02-11 21:01:37 -08001630func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001631
1632 classifierInfo := make(map[string]interface{})
1633 actionInfo := make(map[string]interface{})
1634
1635 classifierInfo[EthType] = uint32(LldpEthType)
1636 classifierInfo[PacketTagType] = Untagged
1637 actionInfo[TrapToHost] = true
1638
1639 // LLDP flow is installed to trap LLDP packets on the NNI port.
1640 // We manage flow_id resource pool on per PON port basis.
1641 // Since this situation is tricky, as a hack, we pass the NNI port
1642 // index (network_intf_id) as PON port Index for the flow_id resource
1643 // pool. Also, there is no ONU Id available for trapping LLDP packets
1644 // on NNI port, use onu_id as -1 (invalid)
1645 // ****************** CAVEAT *******************
1646 // This logic works if the NNI Port Id falls within the same valid
1647 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1648 // we need to have a re-look at this.
1649 // *********************************************
1650
1651 var onuID = -1
1652 var uniID = -1
1653 var gemPortID = -1
1654
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001655 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001656 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301657 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001658 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001659 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001660 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001661 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001662 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001663
David K. Bainbridge794735f2020-02-11 21:01:37 -08001664 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1665 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301666 return olterrors.NewErrInvalidValue(
1667 log.Fields{
1668 "classifier": classifierInfo,
1669 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001670 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001671 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301672 log.Fields{
1673 "classifier": *classifierProto,
1674 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001675 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001676 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301677 return olterrors.NewErrInvalidValue(
1678 log.Fields{
1679 "action": actionInfo,
1680 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001681 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001682 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301683 log.Fields{
1684 "action": *actionProto,
1685 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001686
1687 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1688 OnuId: int32(onuID), // OnuId not required
1689 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001690 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001691 FlowType: Downstream,
1692 NetworkIntfId: int32(networkInterfaceID),
1693 GemportId: int32(gemPortID),
1694 Classifier: classifierProto,
1695 Action: actionProto,
1696 Priority: int32(flow.Priority),
1697 Cookie: flow.Cookie,
1698 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001699 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001700 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301701 log.Fields{
1702 "flow": downstreamflow,
1703 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001704 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001705 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301706 log.Fields{
1707 "device-id": f.deviceHandler.device.Id,
1708 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001709 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001710
David K. Bainbridge794735f2020-02-11 21:01:37 -08001711 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301712}
1713
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001714func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1715 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001716}
1717
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001718//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001719func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001720 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1721 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1722 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001723 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301724 log.Fields{
1725 "intf-id": intfID,
1726 "onu-id": onuID,
1727 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001728 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001729 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301730 return nil, olterrors.NewErrNotFound("onu-child-device",
1731 log.Fields{
1732 "onu-id": onuID,
1733 "intf-id": intfID,
1734 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001735 }
khenaidoo106c61a2021-08-11 18:05:46 -04001736 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 -07001737 //better to ad the device to cache here.
1738 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1739 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001740 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301741 log.Fields{
1742 "intf-id": intfID,
1743 "onu-id": onuID,
1744 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001745 }
1746
1747 return onuDev.(*OnuDevice), nil
1748}
1749
1750//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001751func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1752 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301753 log.Fields{
1754 "pon-port": intfID,
1755 "onu-id": onuID,
1756 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001757 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001758 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001759 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301760 return nil, olterrors.NewErrNotFound("onu",
1761 log.Fields{
1762 "interface-id": parentPortNo,
1763 "onu-id": onuID,
1764 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001765 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301766 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001767 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301768 log.Fields{
1769 "device-id": f.deviceHandler.device.Id,
1770 "child_device_id": onuDevice.Id,
1771 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301772 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301773}
1774
Neha Sharma96b7bf22020-06-15 10:37:32 +00001775func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1776 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301777 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001778 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301779 log.Fields{
1780 "intf-id": intfID,
1781 "onu-id": onuID,
1782 "uni-id": uniID,
1783 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001784 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301785 }
1786
khenaidoodc2116e2021-10-19 17:33:19 -04001787 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001788 DeviceId: onuDev.deviceID,
1789 UniId: uniID,
1790 TpInstancePath: tpPath,
1791 GemPortId: gemPortID,
1792 }
1793 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1794
1795 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301796 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1797 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001798 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1799 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301800 "onu-id": onuDev.deviceID,
1801 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001802 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301803 }
khenaidoo106c61a2021-08-11 18:05:46 -04001804
Neha Sharma96b7bf22020-06-15 10:37:32 +00001805 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301806 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001807 "msg": delGemPortMsg,
1808 "from-adapter": f.deviceHandler.device.Type,
1809 "to-adapter": onuDev.deviceType,
1810 "device-id": f.deviceHandler.device.Id,
1811 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301812 return nil
1813}
1814
Neha Sharma96b7bf22020-06-15 10:37:32 +00001815func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1816 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301817 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001818 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301819 log.Fields{
1820 "intf-id": intfID,
1821 "onu-id": onuID,
1822 "uni-id": uniID,
1823 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001824 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301825 }
1826
khenaidoodc2116e2021-10-19 17:33:19 -04001827 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001828 DeviceId: onuDev.deviceID,
1829 UniId: uniID,
1830 TpInstancePath: tpPath,
1831 AllocId: allocID,
1832 }
1833
Neha Sharma96b7bf22020-06-15 10:37:32 +00001834 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301835 log.Fields{
1836 "msg": *delTcontMsg,
1837 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001838
1839 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301840 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1841 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001842 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1843 "to-adapter": onuDev.adapterEndpoint,
1844 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301845 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001846 "device-id": f.deviceHandler.device.Id}, err)
1847
Girish Gowdra6b130582019-11-20 16:45:20 +05301848 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001849 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301850 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001851 "msg": delTcontMsg,
1852 "device-id": f.deviceHandler.device.Id,
1853 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301854 return nil
1855}
1856
Girish Gowdrac3037402020-01-22 20:29:53 +05301857// Once the gemport is released for a given onu, it also has to be cleared from local cache
1858// which was used for deriving the gemport->logicalPortNo during packet-in.
1859// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1860// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001861func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001862 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301863 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001864 "gem-port-id": gemPortID,
1865 "intf-id": intfID,
1866 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001867 "device-id": f.deviceHandler.device.Id})
1868 f.onuGemInfoLock.RLock()
1869 onugem, ok := f.onuGemInfoMap[onuID]
1870 f.onuGemInfoLock.RUnlock()
1871 if !ok {
1872 logger.Warnw(ctx, "onu gem info already cleared from cache", log.Fields{
1873 "gem-port-id": gemPortID,
1874 "intf-id": intfID,
1875 "onu-id": onuID,
1876 "device-id": f.deviceHandler.device.Id})
1877 return
1878 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001879deleteLoop:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001880 for j, gem := range onugem.GemPorts {
1881 // If the gemport is found, delete it from local cache.
1882 if gem == gemPortID {
1883 onugem.GemPorts = append(onugem.GemPorts[:j], onugem.GemPorts[j+1:]...)
1884 f.onuGemInfoLock.Lock()
1885 f.onuGemInfoMap[onuID] = onugem
1886 f.onuGemInfoLock.Unlock()
1887 logger.Infow(ctx, "removed-gemport-from-local-cache",
1888 log.Fields{
1889 "intf-id": intfID,
1890 "onu-id": onuID,
1891 "deletedgemport-id": gemPortID,
1892 "gemports": onugem.GemPorts,
1893 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001894 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301895 }
1896 }
1897}
1898
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301899//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001900// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001901func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Gamze Abaka411ef2f2021-11-22 08:38:08 +00001902 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001903
1904 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001905
Girish Gowdraa482f272021-03-24 23:04:19 -07001906 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1907 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001908 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1909 log.Fields{
1910 "tpPath": tpPath,
1911 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001912
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001913 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001914 if err != nil || techprofileInst == nil {
1915 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1916 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1917 if childDevice == nil {
1918 // happens when subscriber un-provision is immediately followed by child device delete
1919 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1920 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1921 return nil
1922 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001923 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1924 log.Fields{
1925 "tp-id": tpID,
1926 "path": tpPath}, err)
1927 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001928
1929 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001930 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001931 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001932 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1933 gemPortID := gemPort.GemportId
1934 used := f.isGemPortUsedByAnotherFlow(gemPortID, flowID)
1935 if used {
1936 f.gemToFlowIDsKey.RLock()
1937 flowIDs := f.gemToFlowIDs[gemPortID]
1938 f.gemToFlowIDsKey.RUnlock()
1939
1940 for i, flowIDinMap := range flowIDs {
1941 if flowIDinMap == flowID {
1942 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1943 f.gemToFlowIDsKey.Lock()
1944 f.gemToFlowIDs[gemPortID] = flowIDs
1945 f.gemToFlowIDsKey.Unlock()
1946 // everytime gemToFlowIDs cache is updated the same should be updated
1947 // in kv store by calling UpdateFlowIDsForGem
1948 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, gemPortID, flowIDs); err != nil {
1949 return err
1950 }
1951 break
1952 }
1953 }
1954 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1955 log.Fields{
1956 "gemport-id": gemPortID,
1957 "usedByFlows": flowIDs,
1958 "currentFlow": flowID,
1959 "device-id": f.deviceHandler.device.Id})
1960 allGemPortsFree = false
1961 }
1962 }
1963 if !allGemPortsFree {
1964 return nil
1965 }
1966 }
1967
1968 logger.Debugw(ctx, "all-gem-ports-are-free-to-be-deleted", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
1969 switch techprofileInst := techprofileInst.(type) {
1970 case *tp_pb.TechProfileInstance:
1971 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
1972 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQueue)
1973 if !allocExists {
Girish Gowdraa482f272021-03-24 23:04:19 -07001974 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001975 logger.Warn(ctx, err)
1976 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001977 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001978 logger.Warn(ctx, err)
1979 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001980
1981 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
1982 if err := f.RemoveSchedulerQueues(ctx, schedQueue); err != nil {
1983 logger.Warn(ctx, err)
1984 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001985 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001986 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId)
1987
1988 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
1989 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
1990 if err := f.RemoveSchedulerQueues(ctx, schedQueue); err != nil {
1991 logger.Warn(ctx, err)
1992 }
1993 }
1994
1995 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1996 gemPortID := gemPort.GemportId
1997 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), gemPortID)
1998 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), gemPortID) // ignore error and proceed.
1999
2000 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gemPortID); err == nil {
2001 //everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
2002 // by calling DeleteFlowIDsForGem
2003 f.gemToFlowIDsKey.Lock()
2004 delete(f.gemToFlowIDs, gemPortID)
2005 f.gemToFlowIDsKey.Unlock()
2006 } else {
2007 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
2008 log.Fields{
2009 "err": err,
2010 "intf": intfID,
2011 "onu-id": onuID,
2012 "uni-id": uniID,
2013 "device-id": f.deviceHandler.device.Id,
2014 "gemport-id": gemPortID})
2015 }
2016
2017 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), gemPortID)
2018
2019 // Delete the gem port on the ONU.
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002020 if sendDeleteGemRequest {
2021 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPortID, tpPath); err != nil {
2022 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2023 log.Fields{
2024 "err": err,
2025 "intfID": intfID,
2026 "onu-id": onuID,
2027 "uni-id": uniID,
2028 "device-id": f.deviceHandler.device.Id,
2029 "gemport-id": gemPortID})
2030 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00002031 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002032 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002033 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002034 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07002035 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002036 logger.Warn(ctx, err)
2037 }
Girish Gowdraa482f272021-03-24 23:04:19 -07002038 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002039 logger.Warn(ctx, err)
2040 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002041 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002042 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002043 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002044 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302045 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002046 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302047 "onu-id": onuID,
2048 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002049 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002050 "alloc-id": techprofileInst.AllocId,
2051 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002052 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002053 default:
2054 logger.Errorw(ctx, "error-unknown-tech",
2055 log.Fields{
2056 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002057 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302058 return nil
2059}
2060
David K. Bainbridge794735f2020-02-11 21:01:37 -08002061// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002062func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002063 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302064 log.Fields{
2065 "flowDirection": flowDirection,
2066 "flow": *flow,
2067 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002068
2069 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002070 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002071 }
2072
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302073 var ethType, ipProto, inPort uint32
2074 for _, field := range flows.GetOfbFields(flow) {
2075 if field.Type == flows.IP_PROTO {
2076 ipProto = field.GetIpProto()
2077 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"ipProto": ipProto})
2078 } else if field.Type == flows.ETH_TYPE {
2079 ethType = field.GetEthType()
2080 logger.Debugw(ctx, "field-type-eth-type", log.Fields{"ethType": ethType})
2081 } else if field.Type == flows.IN_PORT {
2082 inPort = field.GetPort()
2083 logger.Debugw(ctx, "field-type-in-port", log.Fields{"inPort": inPort})
2084 }
2085 }
2086 portType := plt.IntfIDToPortTypeName(inPort)
2087 if (ethType == uint32(LldpEthType) || ipProto == uint32(IPProtoDhcp) || ipProto == uint32(IgmpProto)) &&
2088 (portType == voltha.Port_ETHERNET_NNI) {
2089 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: -1, OnuId: -1, UniId: -1, TechProfileId: 0, FlowType: Downstream}
2090 logger.Debugw(ctx, "nni-trap-flow-to-be-deleted", log.Fields{"flow": flow})
2091 return f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id)
2092 // No more processing needed for trap from nni flows.
2093 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302094
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302095 portNum, Intf, onu, uni, _, _, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302096 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002097 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002098 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302099 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002100 onuID := int32(onu)
2101 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002102 tpID, err := getTpIDFromFlow(ctx, flow)
2103 if err != nil {
2104 return olterrors.NewErrNotFound("tp-id",
2105 log.Fields{
2106 "flow": flow,
2107 "intf-id": Intf,
2108 "onu-id": onuID,
2109 "uni-id": uniID,
2110 "device-id": f.deviceHandler.device.Id}, err)
2111 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302112
Neha Sharma96b7bf22020-06-15 10:37:32 +00002113 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302114 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002115 "flow-id": flow.Id,
2116 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302117 "onu-id": onuID,
2118 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302119
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002120 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2121 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002122 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2123 return err
2124 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002125
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002126 // Delete the flow-id to gemport list entry from the map now the flow is deleted.
Gamze Abaka745ccb72021-11-18 11:29:58 +00002127 f.flowIDToGemsLock.Lock()
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002128 delete(f.flowIDToGems, flow.Id)
2129 f.flowIDToGemsLock.Unlock()
2130
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002131 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002132 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2133 "flow-id": flow.Id,
2134 "device-id": f.deviceHandler.device.Id,
2135 "onu-id": onuID,
2136 "intf": Intf,
2137 "err": err,
2138 })
2139 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302140 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002141
Girish Gowdra82c80982021-03-26 16:22:02 -07002142 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2143 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2144 return err
2145 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002146 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002147}
2148
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002149//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002150func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002151
Matteo Scandolof16389e2021-05-18 00:47:08 +00002152 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302153 var direction string
2154 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002155
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302156 for _, action := range flows.GetActions(flow) {
2157 if action.Type == flows.OUTPUT {
2158 if out := action.GetOutput(); out != nil {
2159 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002160 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302161 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002162 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002163 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002164 }
2165 }
2166 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002167
2168 if flows.HasGroup(flow) {
2169 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002170 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002171 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302172 direction = Upstream
2173 } else {
2174 direction = Downstream
2175 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302176
Girish Gowdracefae192020-03-19 18:14:10 -07002177 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002178 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002179
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002180 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002181}
2182
Esin Karamanae41e2b2019-12-17 18:13:13 +00002183//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2184func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002185 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002186 if ethType, ok := classifierInfo[EthType]; ok {
2187 if ethType.(uint32) == IPv4EthType {
2188 if ipProto, ok := classifierInfo[IPProto]; ok {
2189 if ipProto.(uint32) == IgmpProto {
2190 return true
2191 }
2192 }
2193 }
2194 }
2195 }
2196 return false
2197}
2198
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002199// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002200func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002201 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2202 // The device itself is going to be reset as part of deletion. So nothing to be done.
2203 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2204 return nil
2205 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002206 // Step1 : Fill flowControlBlock
2207 // Step2 : Push the flowControlBlock to ONU channel
2208 // Step3 : Wait on response channel for response
2209 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002210 startTime := time.Now()
2211 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002212 errChan := make(chan error)
2213 flowCb := flowControlBlock{
2214 ctx: ctx,
2215 addFlow: addFlow,
2216 flow: flow,
2217 flowMetadata: flowMetadata,
2218 errChan: &errChan,
2219 }
2220 inPort, outPort := getPorts(flow)
2221 var onuID uint32
2222 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002223 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002224 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002225 if f.flowHandlerRoutineActive[onuID] {
2226 // inPort or outPort is InvalidPort for trap-from-nni flows.
2227 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2228 // Send the flowCb on the ONU flow channel
2229 f.incomingFlows[onuID] <- flowCb
2230 // Wait on the channel for flow handlers return value
2231 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002232 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002233 return err
2234 }
2235 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2236 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002237}
2238
2239// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2240// 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 -07002241func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002242 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002243 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002244 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002245 // block on the channel to receive an incoming flow
2246 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002247 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002248 if flowCb.addFlow {
2249 logger.Info(flowCb.ctx, "adding-flow-start")
2250 startTime := time.Now()
2251 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2252 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2253 // Pass the return value over the return channel
2254 *flowCb.errChan <- err
2255 } else {
2256 logger.Info(flowCb.ctx, "removing-flow-start")
2257 startTime := time.Now()
2258 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2259 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2260 // Pass the return value over the return channel
2261 *flowCb.errChan <- err
2262 }
2263 case <-stopHandler:
2264 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2265 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002266 }
2267 }
2268}
2269
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002270// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002271func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002272 for i, v := range f.stopFlowHandlerRoutine {
2273 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002274 select {
2275 case v <- true:
2276 case <-time.After(time.Second * 5):
2277 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2278 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002279 }
2280 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002281 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002282 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2283}
2284
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002285// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302286// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002287func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002288 classifierInfo := make(map[string]interface{})
2289 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002290 var UsMeterID uint32
2291 var DsMeterID uint32
2292
Neha Sharma96b7bf22020-06-15 10:37:32 +00002293 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302294 log.Fields{
2295 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002296 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002297 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002298
Neha Sharma96b7bf22020-06-15 10:37:32 +00002299 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002300 if err != nil {
2301 // Error logging is already done in the called function
2302 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002303 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302304 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002305
Esin Karamanccb714b2019-11-29 15:02:06 +00002306 if flows.HasGroup(flow) {
2307 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002308 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002309 }
2310
manikkaraj k17652a72019-05-06 09:06:36 -04002311 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002312 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002313 if err != nil {
2314 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002315 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002316 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002317
Neha Sharma96b7bf22020-06-15 10:37:32 +00002318 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302319 log.Fields{
2320 "classifierinfo_inport": classifierInfo[InPort],
2321 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002322 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002323
Humera Kouser94d7a842019-08-25 19:04:32 -04002324 if ethType, ok := classifierInfo[EthType]; ok {
2325 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002326 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002327 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002328 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002329 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002330 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002331 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2332 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2333 }
2334 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002335 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002336 if ipProto, ok := classifierInfo[IPProto]; ok {
2337 if ipProto.(uint32) == IPProtoDhcp {
2338 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302339 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002340 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002341 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002342 }
2343 }
2344 }
2345 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002346 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002347 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002348 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002349 }
A R Karthick1f85b802019-10-11 05:06:05 +00002350
npujarec5762e2020-01-01 14:08:48 +05302351 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002352 // also update flowmgr cache
2353 f.onuGemInfoLock.Lock()
2354 onugem, ok := f.onuGemInfoMap[onuID]
2355 if ok {
2356 found := false
2357 for _, uni := range onugem.UniPorts {
2358 if uni == portNo {
2359 found = true
2360 break
2361 }
2362 }
2363 if !found {
2364 onugem.UniPorts = append(onugem.UniPorts, portNo)
2365 f.onuGemInfoMap[onuID] = onugem
2366 logger.Infow(ctx, "added uni port to onugem cache", log.Fields{"uni": portNo})
2367 }
2368 }
2369 f.onuGemInfoLock.Unlock()
A R Karthick1f85b802019-10-11 05:06:05 +00002370
Girish Gowdra6071f382021-12-14 12:52:04 +05302371 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002372 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302373 return olterrors.NewErrNotFound("tpid-for-flow",
2374 log.Fields{
2375 "flow": flow,
2376 "intf-id": IntfID,
2377 "onu-id": onuID,
2378 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002379 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002380 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302381 log.Fields{
Girish Gowdra6071f382021-12-14 12:52:04 +05302382 "tp-id": tpID,
Shrey Baid26912972020-04-16 21:02:31 +05302383 "intf-id": intfID,
2384 "onu-id": onuID,
2385 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002386 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002387 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002388 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302389 if err := f.validateMeter(ctx, Upstream, UsMeterID, intfID, onuID, uniID, tpID); err != nil {
2390 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2391 return err
2392 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002393 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002394 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002395 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302396 if err := f.validateMeter(ctx, Downstream, DsMeterID, intfID, onuID, uniID, tpID); err != nil {
2397 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2398 return err
2399 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002400 }
Girish Gowdra6071f382021-12-14 12:52:04 +05302401 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, tpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002402}
Girish Gowdra3d633032019-12-10 16:37:05 +05302403
Esin Karamanccb714b2019-11-29 15:02:06 +00002404// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002405func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302406 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002407 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302408 "classifier-info": classifierInfo,
2409 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002410
Esin Karaman65409d82020-03-18 10:58:18 +00002411 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002412 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002413 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002414 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002415
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002416 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002417
David K. Bainbridge794735f2020-02-11 21:01:37 -08002418 onuID := NoneOnuID
2419 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002420
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002421 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002422 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002423 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002424 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002425 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2426 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002427 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002428 }
2429 groupID := actionInfo[GroupID].(uint32)
2430 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002431 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002432 FlowType: Multicast,
2433 NetworkIntfId: int32(networkInterfaceID),
2434 GroupId: groupID,
2435 Classifier: classifierProto,
2436 Priority: int32(flow.Priority),
2437 Cookie: flow.Cookie}
2438
Kent Hagermane6ff1012020-07-14 15:07:53 -04002439 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002440 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002441 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002442 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002443 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002444 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002445 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002446 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002447 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002448 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002449 //cached group can be removed now
2450 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002451 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002452 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002453 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002454
David K. Bainbridge794735f2020-02-11 21:01:37 -08002455 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002456}
2457
Esin Karaman65409d82020-03-18 10:58:18 +00002458//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2459func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2460 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002461 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002462 if err != nil {
2463 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2464 }
2465 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002466 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002467
2468 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2469 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002470}
2471
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002472//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002473func (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 -07002474
Neha Sharma96b7bf22020-06-15 10:37:32 +00002475 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302476 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002477 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302478 log.Fields{
2479 "intf-id": intfID,
2480 "onu-id": onuID,
2481 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002482 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302483 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002484 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002485
Neha Sharma96b7bf22020-06-15 10:37:32 +00002486 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002487 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002488 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002489 UniId: uniID,
2490 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002491 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002492 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002493 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002494
2495 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2496 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302497 return olterrors.NewErrCommunication("send-techprofile-download-request",
2498 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002499 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302500 "to-adapter": onuDev.deviceType,
2501 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002502 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002503 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002504 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302505 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302506}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002507
Girish Gowdra197acc12021-08-16 10:59:45 -07002508//AddOnuInfoToFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2509func (f *OpenOltFlowMgr) AddOnuInfoToFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302510
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002511 f.onuGemInfoLock.RLock()
2512 _, ok := f.onuGemInfoMap[onuID]
2513 f.onuGemInfoLock.RUnlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002514 // If the ONU already exists in onuGemInfo list, nothing to do
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002515 if ok {
2516 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2517 log.Fields{"onuID": onuID,
2518 "serialNum": serialNum})
2519 return nil
Girish Gowdra9602eb42020-09-09 15:50:39 -07002520 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002521
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002522 onuGemInfo := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2523 f.onuGemInfoLock.Lock()
2524 f.onuGemInfoMap[onuID] = &onuGemInfo
2525 f.onuGemInfoLock.Unlock()
2526 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onuID, onuGemInfo); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002527 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302528 }
Girish Gowdra197acc12021-08-16 10:59:45 -07002529 logger.Infow(ctx, "added-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302530 log.Fields{
2531 "intf-id": intfID,
2532 "onu-id": onuID,
2533 "serial-num": serialNum,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002534 "onu": onuGemInfo,
Shrey Baid26912972020-04-16 21:02:31 +05302535 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002536 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002537}
2538
Girish Gowdra197acc12021-08-16 10:59:45 -07002539//RemoveOnuInfoFromFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2540func (f *OpenOltFlowMgr) RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32) error {
2541
2542 f.onuGemInfoLock.Lock()
2543 delete(f.onuGemInfoMap, onuID)
2544 f.onuGemInfoLock.Unlock()
2545
2546 if err := f.resourceMgr.DelOnuGemInfo(ctx, intfID, onuID); err != nil {
2547 return err
2548 }
2549 logger.Infow(ctx, "deleted-onuinfo",
2550 log.Fields{
2551 "intf-id": intfID,
2552 "onu-id": onuID,
2553 "device-id": f.deviceHandler.device.Id})
2554 return nil
2555}
2556
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302557//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302558func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002559
Neha Sharma96b7bf22020-06-15 10:37:32 +00002560 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302561 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002562 "gem-port-id": gemPort,
2563 "intf-id": intfID,
2564 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002565 "device-id": f.deviceHandler.device.Id})
2566 f.onuGemInfoLock.RLock()
2567 onugem, ok := f.onuGemInfoMap[onuID]
2568 f.onuGemInfoLock.RUnlock()
2569 if !ok {
2570 logger.Warnw(ctx, "onu gem info is missing", log.Fields{
2571 "gem-port-id": gemPort,
2572 "intf-id": intfID,
2573 "onu-id": onuID,
2574 "device-id": f.deviceHandler.device.Id})
2575 return
2576 }
2577
2578 if onugem.OnuID == onuID {
2579 // check if gem already exists , else update the cache and kvstore
2580 for _, gem := range onugem.GemPorts {
2581 if gem == gemPort {
2582 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2583 log.Fields{
2584 "gem": gemPort,
2585 "device-id": f.deviceHandler.device.Id})
2586 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302587 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302588 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002589 onugem.GemPorts = append(onugem.GemPorts, gemPort)
2590 f.onuGemInfoLock.Lock()
2591 f.onuGemInfoMap[onuID] = onugem
2592 f.onuGemInfoLock.Unlock()
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002593 logger.Debugw(ctx, "updated onu gem info from cache", log.Fields{"onugem": onugem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002594 } else {
2595 logger.Warnw(ctx, "mismatched onu id", log.Fields{
2596 "gem-port-id": gemPort,
2597 "intf-id": intfID,
2598 "onu-id": onuID,
2599 "device-id": f.deviceHandler.device.Id})
2600 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302601 }
npujarec5762e2020-01-01 14:08:48 +05302602 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302603 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002604 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302605 log.Fields{
2606 "intf-id": intfID,
2607 "onu-id": onuID,
2608 "gemPort": gemPort,
2609 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002610 return
2611 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002612 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302613 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002614 "gem-port-id": gemPort,
2615 "intf-id": intfID,
2616 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002617 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002618}
2619
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002620//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302621func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002622 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002623
2624 if packetIn.IntfType == "pon" {
2625 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002626 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002627 onuID, uniID := packetIn.OnuId, packetIn.UniId
2628 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 +00002629
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002630 if packetIn.PortNo != 0 {
2631 logicalPortNum = packetIn.PortNo
2632 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002633 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002634 }
2635 // 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 +00002636 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002637 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002638 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002639 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002640
2641 if logger.V(log.DebugLevel) {
2642 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2643 log.Fields{
2644 "logical-port-num": logicalPortNum,
2645 "intf-type": packetIn.IntfType,
2646 "packet": hex.EncodeToString(packetIn.Pkt),
2647 })
2648 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002649 return logicalPortNum, nil
2650}
2651
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002652//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002653func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002654 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002655
2656 ctag, priority, err := getCTagFromPacket(ctx, packet)
2657 if err != nil {
2658 return 0, err
2659 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302660
Esin Karaman7fb80c22020-07-16 14:23:33 +00002661 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002662 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002663 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002664 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002665 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302666 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002667 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302668 log.Fields{
2669 "pktinkey": pktInkey,
2670 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002671
2672 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002673 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302674 //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 +00002675 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302676 if err == nil {
2677 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002678 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302679 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002680 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002681 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302682 log.Fields{
2683 "pktinkey": pktInkey,
2684 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302685 return gemPortID, nil
2686 }
2687 }
Shrey Baid26912972020-04-16 21:02:31 +05302688 return uint32(0), olterrors.NewErrNotFound("gem-port",
2689 log.Fields{
2690 "pktinkey": pktInkey,
2691 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002692
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002693}
2694
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002695func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2696 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002697 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002698 classifier[PacketTagType] = DoubleTag
2699 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002700 /* We manage flowId resource pool on per PON port basis.
2701 Since this situation is tricky, as a hack, we pass the NNI port
2702 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002703 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002704 on NNI port, use onu_id as -1 (invalid)
2705 ****************** CAVEAT *******************
2706 This logic works if the NNI Port Id falls within the same valid
2707 range of PON Port Ids. If this doesn't work for some OLT Vendor
2708 we need to have a re-look at this.
2709 *********************************************
2710 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002711 onuID := -1
2712 uniID := -1
2713 gemPortID := -1
2714 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002715 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302716 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302717 return olterrors.NewErrNotFound("nni-intreface-id",
2718 log.Fields{
2719 "classifier": classifier,
2720 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002721 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302722 }
2723
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002724 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002725 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002726 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002727 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002728
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002729 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2730 log.Fields{
2731 "classifier": classifier,
2732 "action": action,
2733 "flowId": logicalFlow.Id,
2734 "intf-id": networkInterfaceID})
2735
David K. Bainbridge794735f2020-02-11 21:01:37 -08002736 classifierProto, err := makeOpenOltClassifierField(classifier)
2737 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002738 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002739 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002740 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002741 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002742 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002743 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002744 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002745 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002746 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2747 OnuId: int32(onuID), // OnuId not required
2748 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002749 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002750 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002751 AllocId: int32(allocID), // AllocId not used
2752 NetworkIntfId: int32(networkInterfaceID),
2753 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002754 Classifier: classifierProto,
2755 Action: actionProto,
2756 Priority: int32(logicalFlow.Priority),
2757 Cookie: logicalFlow.Cookie,
2758 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002759 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002760 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002761 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002762 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002763 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002764}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002765
Esin Karamanae41e2b2019-12-17 18:13:13 +00002766//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2767func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2768 var packetType string
2769 ovid, ivid := false, false
2770 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2771 vid := vlanID & VlanvIDMask
2772 if vid != ReservedVlan {
2773 ovid = true
2774 }
2775 }
2776 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2777 vid := uint32(metadata)
2778 if vid != ReservedVlan {
2779 ivid = true
2780 }
2781 }
2782 if ovid && ivid {
2783 packetType = DoubleTag
2784 } else if !ovid && !ivid {
2785 packetType = Untagged
2786 } else {
2787 packetType = SingleTag
2788 }
2789 return packetType
2790}
2791
2792//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002793func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002794 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002795 action := make(map[string]interface{})
2796 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2797 action[TrapToHost] = true
2798 /* We manage flowId resource pool on per PON port basis.
2799 Since this situation is tricky, as a hack, we pass the NNI port
2800 index (network_intf_id) as PON port Index for the flowId resource
2801 pool. Also, there is no ONU Id available for trapping packets
2802 on NNI port, use onu_id as -1 (invalid)
2803 ****************** CAVEAT *******************
2804 This logic works if the NNI Port Id falls within the same valid
2805 range of PON Port Ids. If this doesn't work for some OLT Vendor
2806 we need to have a re-look at this.
2807 *********************************************
2808 */
2809 onuID := -1
2810 uniID := -1
2811 gemPortID := -1
2812 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002813 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002814 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302815 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002816 "classifier": classifier,
2817 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002818 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002819 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002820 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002821 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002822 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002823 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002824
David K. Bainbridge794735f2020-02-11 21:01:37 -08002825 classifierProto, err := makeOpenOltClassifierField(classifier)
2826 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002827 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002828 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002829 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002830 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002831 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002832 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002833 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002834 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002835 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2836 OnuId: int32(onuID), // OnuId not required
2837 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002838 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002839 FlowType: Downstream,
2840 AllocId: int32(allocID), // AllocId not used
2841 NetworkIntfId: int32(networkInterfaceID),
2842 GemportId: int32(gemPortID), // GemportId not used
2843 Classifier: classifierProto,
2844 Action: actionProto,
2845 Priority: int32(logicalFlow.Priority),
2846 Cookie: logicalFlow.Cookie,
2847 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002848 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002849 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002850 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002851 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002852
David K. Bainbridge794735f2020-02-11 21:01:37 -08002853 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002854}
2855
salmansiddiqui7ac62132019-08-22 03:58:50 +00002856func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2857 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302858 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002859 }
2860 if Dir == tp_pb.Direction_UPSTREAM {
2861 return "upstream", nil
2862 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2863 return "downstream", nil
2864 }
2865 return "", nil
2866}
2867
Kent Hagermane6ff1012020-07-14 15:07:53 -04002868// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302869func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002870 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002871 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002872 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002873 intfID := args[IntfID]
2874 onuID := args[OnuID]
2875 uniID := args[UniID]
2876 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002877 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002878 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002879 gemToAes := make(map[uint32]bool)
2880
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002881 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002882 var direction = tp_pb.Direction_UPSTREAM
2883 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002884 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002885 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002886 attributes = TpInst.UpstreamGemPortAttributeList
2887 } else {
2888 attributes = TpInst.DownstreamGemPortAttributeList
2889 direction = tp_pb.Direction_DOWNSTREAM
2890 }
2891 default:
2892 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002893 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002894 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002895
2896 if len(gemPorts) == 1 {
2897 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002898 gemPortID = gemPorts[0]
2899 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002900 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2901 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002902 pBitMap := attributes[idx].PbitMap
2903 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2904 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2905 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002906 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002907 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2908 if pbitSet == pbit1 {
2909 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2910 pbitToGem[pcp] = gemID
2911 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002912 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002913 }
2914 }
2915 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002916 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2917 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2918 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002919 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002920 }
2921
Gamze Abaka7650be62021-02-26 10:50:36 +00002922 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2923 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2924
salmansiddiqui7ac62132019-08-22 03:58:50 +00002925 if ipProto, ok := classifierInfo[IPProto]; ok {
2926 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002927 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002928 "tp-id": tpID,
2929 "alloc-id": allocID,
2930 "intf-id": intfID,
2931 "onu-id": onuID,
2932 "uni-id": uniID,
2933 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002934 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002935 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002936 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002937 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2938 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002939 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002940 }
2941
Girish Gowdra32625212020-04-29 11:26:35 -07002942 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002943 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302944 log.Fields{
2945 "intf-id": intfID,
2946 "onu-id": onuID,
2947 "uni-id": uniID,
2948 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002949 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002950 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002951 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2952 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002953 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002954 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002955 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002956 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002957 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002958 }
2959 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002960 if ethType.(uint32) == EapEthType {
2961 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002962 "intf-id": intfID,
2963 "onu-id": onuID,
2964 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002965 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002966 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002967 var vlanID uint32
2968 if val, ok := classifierInfo[VlanVid]; ok {
2969 vlanID = (val.(uint32)) & VlanvIDMask
2970 } else {
2971 vlanID = DefaultMgmtVlan
2972 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002973 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002974 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002975 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2976 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002977 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002978 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002979 } else if ethType.(uint32) == PPPoEDEthType {
2980 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2981 "tp-id": tpID,
2982 "alloc-id": allocID,
2983 "intf-id": intfID,
2984 "onu-id": onuID,
2985 "uni-id": uniID,
2986 })
2987 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002988 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002989 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002990 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2991 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002992 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002993 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002994 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002995 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002996 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002997 "intf-id": intfID,
2998 "onu-id": onuID,
2999 "uni-id": uniID,
3000 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003001 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00003002 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003003 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003004 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
3005 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003006 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00003007 }
Gamze Abaka7650be62021-02-26 10:50:36 +00003008 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003009 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003010 "intf-id": intfID,
3011 "onu-id": onuID,
3012 "uni-id": uniID,
3013 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003014 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00003015 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003016 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003017 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
3018 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003019 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00003020 }
3021 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003022 return olterrors.NewErrInvalidValue(log.Fields{
3023 "intf-id": intfID,
3024 "onu-id": onuID,
3025 "uni-id": uniID,
3026 "classifier": classifierInfo,
3027 "action": actionInfo,
3028 "flow": flow},
3029 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003030 }
3031 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04003032 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003033 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003034 logger.Warn(ctx, err)
3035 }
3036 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003037 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00003038}
3039
Gamze Abaka745ccb72021-11-18 11:29:58 +00003040func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32, flowID uint64) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003041 f.gemToFlowIDsKey.RLock()
3042 flowIDList := f.gemToFlowIDs[gemPortID]
3043 f.gemToFlowIDsKey.RUnlock()
Gamze Abaka745ccb72021-11-18 11:29:58 +00003044 if len(flowIDList) > 0 {
3045 for _, id := range flowIDList {
3046 if flowID != id {
3047 return true
Gamze Abakafee36392019-10-03 11:17:24 +00003048 }
3049 }
3050 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00003051 return false
Gamze Abakacb0e6772021-06-10 08:32:12 +00003052}
Girish Gowdra54934262019-11-13 14:19:55 +05303053
Gamze Abakacb0e6772021-06-10 08:32:12 +00003054func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003055 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
3056 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
3057 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 +00003058 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303059 for i := 0; i < len(tpInstances); i++ {
3060 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00003061 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003062 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Gamze Abakacb0e6772021-06-10 08:32:12 +00003063 logger.Debugw(ctx, "alloc-is-in-use",
3064 log.Fields{
3065 "device-id": f.deviceHandler.device.Id,
3066 "intfID": sq.intfID,
3067 "onuID": sq.onuID,
3068 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003069 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00003070 })
3071 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303072 }
3073 }
3074 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003075 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003076}
3077
Neha Sharma96b7bf22020-06-15 10:37:32 +00003078func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003079 for _, field := range flows.GetOfbFields(flow) {
3080 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003081 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003082 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003083 } else if field.Type == flows.ETH_DST {
3084 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003085 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003086 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003087 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003088 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003089 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003090 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003091 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003092 } else if field.Type == flows.VLAN_VID {
Andrea Campanellafaa42152021-10-28 11:50:56 +05303093 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3094 if field.GetVlanVid() != ReservedVlan {
3095 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3096 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3097 }
Scott Baker355d1742019-10-24 10:57:52 -07003098 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003099 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003100 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003101 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003102 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003103 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003104 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003105 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003106 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003107 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003108 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003109 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003110 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003111 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003112 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003113 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003114 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003115 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003116 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003117 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003118 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003119 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003120 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003121 return
3122 }
3123 }
3124}
3125
Neha Sharma96b7bf22020-06-15 10:37:32 +00003126func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003127 for _, action := range flows.GetActions(flow) {
3128 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003129 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003130 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003131 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003132 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003133 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003134 }
Scott Baker355d1742019-10-24 10:57:52 -07003135 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003136 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003137 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003138 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003139 if out := action.GetPush(); out != nil {
3140 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003141 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003142 } else {
3143 actionInfo[PushVlan] = true
3144 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003145 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303146 log.Fields{
3147 "push-tpid": actionInfo[TPID].(uint32),
3148 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003149 }
3150 }
Scott Baker355d1742019-10-24 10:57:52 -07003151 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003152 if out := action.GetSetField(); out != nil {
3153 if field := out.GetField(); field != nil {
3154 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003155 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003156 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003157 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3158 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003159 }
3160 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003161 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003162 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003163 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003164 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003165 }
3166 }
3167 return nil
3168}
3169
Neha Sharma96b7bf22020-06-15 10:37:32 +00003170func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003171 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003172 fieldtype := ofbField.GetType()
3173 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003174 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3175 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003176 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003177 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003178 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003179 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003180 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3181 pcp := ofbField.GetVlanPcp()
3182 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003183 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003184 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003185 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003186 }
3187 }
3188}
3189
Neha Sharma96b7bf22020-06-15 10:37:32 +00003190func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003191 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003192 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003193 } else {
3194 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003195 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003196 }
3197}
3198
Neha Sharma96b7bf22020-06-15 10:37:32 +00003199func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003200 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003201 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003202 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003203 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003204 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003205 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003206 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303207 log.Fields{
3208 "newinport": classifierInfo[InPort].(uint32),
3209 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003210 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303211 return olterrors.NewErrNotFound("child-in-port",
3212 log.Fields{
3213 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3214 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003215 }
3216 }
3217 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003218 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003219 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003220 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003221 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003222 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003223 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303224 log.Fields{
3225 "newoutport": actionInfo[Output].(uint32),
3226 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003227 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303228 return olterrors.NewErrNotFound("out-port",
3229 log.Fields{
3230 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3231 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003232 }
3233 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003234 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003235 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003236 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003237 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303238 log.Fields{
3239 "newinport": actionInfo[Output].(uint32),
3240 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003241 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303242 return olterrors.NewErrNotFound("nni-port",
3243 log.Fields{
3244 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3245 "in-port": classifierInfo[InPort].(uint32),
3246 "out-port": actionInfo[Output].(uint32),
3247 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003248 }
3249 }
3250 }
3251 return nil
3252}
Gamze Abakafee36392019-10-03 11:17:24 +00003253
Neha Sharma96b7bf22020-06-15 10:37:32 +00003254func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003255 /* Metadata 8 bytes:
3256 Most Significant 2 Bytes = Inner VLAN
3257 Next 2 Bytes = Tech Profile ID(TPID)
3258 Least Significant 4 Bytes = Port ID
3259 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3260 subscriber related flows.
3261 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003262 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003263 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003264 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003265 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003266 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003267 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003268}
3269
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003270func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3271 for _, sliceElement := range slice {
3272 if sliceElement == item {
3273 return slice
3274 }
3275 }
3276 return append(slice, item)
3277}
3278
3279func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003280 for _, sliceElement := range slice {
3281 if sliceElement == item {
3282 return slice
3283 }
3284 }
3285 return append(slice, item)
3286}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303287
3288// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003289func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303290
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003291 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303292 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003293 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003294 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003295 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003296 log.Fields{
3297 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003298 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003299 return uint32(0), err
3300 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003301 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303302 return intfID, nil
3303 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003304 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003305 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003306 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003307 log.Fields{
3308 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003309 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003310 return uint32(0), err
3311 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003312 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303313 return intfID, nil
3314 }
3315 return uint32(0), nil
3316}
3317
3318// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003319func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3320 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3321 if err != nil {
3322 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3323 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3324 return
3325 }
3326 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003327
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003328 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003329 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003330 f.packetInGemPortLock.RUnlock()
3331
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303332 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003333 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003334 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 +05303335 log.Fields{
3336 "pktinkey": pktInkey,
3337 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003338 return
3339 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303340 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003341 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003342 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003343 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003344
npujarec5762e2020-01-01 14:08:48 +05303345 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003346 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 +05303347 log.Fields{
3348 "pktinkey": pktInkey,
3349 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303350}
3351
Esin Karaman7fb80c22020-07-16 14:23:33 +00003352//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3353func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3354 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003355 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003356 return 0, 0, errors.New("invalid packet length")
3357 }
3358 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3359 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3360
3361 var index int8
3362 if outerEthType == 0x8100 {
3363 if innerEthType == 0x8100 {
3364 // q-in-q 802.1ad or 802.1q double tagged packet.
3365 // get the inner vlanId
3366 index = 18
3367 } else {
3368 index = 14
3369 }
3370 priority := (packet[index] >> 5) & 0x7
3371 //13 bits composes vlanId value
3372 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3373 return vlan, priority, nil
3374 }
3375 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3376 return 0, 0, nil
3377}
3378
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003379func (f *OpenOltFlowMgr) loadFlowIDsForGemAndGemIDsForFlow(ctx context.Context) {
3380 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - start")
3381 f.onuGemInfoLock.RLock()
3382 f.gemToFlowIDsKey.Lock()
3383 f.flowIDToGemsLock.Lock()
3384 for _, og := range f.onuGemInfoMap {
3385 for _, gem := range og.GemPorts {
3386 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, f.ponPortIdx, gem)
Gamze Abaka6f345c12021-09-08 01:14:33 +00003387 if err == nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003388 f.gemToFlowIDs[gem] = flowIDs
3389 for _, flowID := range flowIDs {
3390 if _, ok := f.flowIDToGems[flowID]; !ok {
3391 f.flowIDToGems[flowID] = []uint32{gem}
3392 } else {
3393 f.flowIDToGems[flowID] = appendUnique32bit(f.flowIDToGems[flowID], gem)
3394 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303395 }
3396 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303397 }
3398 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003399 f.flowIDToGemsLock.Unlock()
3400 f.gemToFlowIDsKey.Unlock()
3401 f.onuGemInfoLock.RUnlock()
3402 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - end")
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303403}
Esin Karamanccb714b2019-11-29 15:02:06 +00003404
Girish Gowdra9602eb42020-09-09 15:50:39 -07003405//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3406// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003407func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003408 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003409 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3410 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003411 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003412 "flow-id": flow.Id,
3413 "device-id": f.deviceHandler.device.Id})
3414 // Remove from device
3415 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3416 // DKB
3417 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3418 log.Fields{
3419 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003420 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003421 return err
3422 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003423
3424 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003425}
3426
khenaidoodc2116e2021-10-19 17:33:19 -04003427func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003428 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003429 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003430 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003431 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003432 }
3433
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003434 switch tpInst := tpInst.(type) {
3435 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003436 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003437 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003438 DeviceId: onuDeviceID,
3439 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003440 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003441 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003442 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003443 case *tp_pb.EponTechProfileInstance:
3444 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003445 DeviceId: onuDeviceID,
3446 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003447 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003448 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003449 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003450 default:
3451 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003452 }
khenaidoodc2116e2021-10-19 17:33:19 -04003453 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003454 DeviceId: onuDeviceID,
3455 UniId: uniID,
3456 TpInstancePath: tpPath,
3457 TechTpInstance: nil,
3458 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003459}
3460
Girish Gowdrabcf98af2021-07-01 08:24:42 -07003461func (f *OpenOltFlowMgr) getOnuGemInfoList(ctx context.Context) []rsrcMgr.OnuGemInfo {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003462 var onuGemInfoLst []rsrcMgr.OnuGemInfo
3463 f.onuGemInfoLock.RLock()
3464 defer f.onuGemInfoLock.RUnlock()
3465 for _, v := range f.onuGemInfoMap {
3466 onuGemInfoLst = append(onuGemInfoLst, *v)
3467 }
3468 return onuGemInfoLst
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003469}
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003470
3471// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3472func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
3473
3474 intfID := sq.intfID
3475 onuID := sq.onuID
3476 uniID := sq.uniID
3477 tpID := sq.tpID
3478
3479 var reverseDirection string
3480 if sq.direction == tp_pb.Direction_UPSTREAM {
3481 reverseDirection = "downstream"
3482 } else {
3483 reverseDirection = "upstream"
3484 }
3485
3486 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
3487 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, intfID, onuID, uniID, tpID); KvStoreMeter != nil {
3488 return
3489 }
3490
3491 // revert-delete tech-profile instance and delete tech profile id for onu
3492 logger.Warnw(ctx, "reverting-tech-profile-instance-and-tech-profile-id-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "tp-id": tpID})
3493 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3494 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
3495 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, onuID, uniID, tpID)
3496
3497 // free gem/alloc
3498 switch techprofileInst := sq.tpInst.(type) {
3499 case *tp_pb.TechProfileInstance:
3500 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
3501 f.resourceMgr.FreeGemPortID(ctx, intfID, onuID, uniID, gem.GemportId)
3502 }
3503 f.resourceMgr.FreeAllocID(ctx, intfID, onuID, uniID, techprofileInst.UsScheduler.AllocId)
3504 }
3505}
3506
3507// revertSchduler is called when CreateQueues request fails
3508func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3509 // revert scheduler
3510 logger.Warnw(ctx, "reverting-scheduler-for-onu", log.Fields{"intf-id": sq.intfID, "onu-id": sq.onuID, "uni-id": sq.uniID, "tp-id": sq.tpID})
3511 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
3512 IntfId: sq.intfID, OnuId: sq.onuID,
3513 UniId: sq.uniID, PortNo: sq.uniPort,
3514 TrafficScheds: TrafficSched})
3515}
Girish Gowdra6071f382021-12-14 12:52:04 +05303516
3517// validateMeter validates if there is a meter mismatch for the given direction. It also clears the stale meter if the reference count is zero
3518func (f *OpenOltFlowMgr) validateMeter(ctx context.Context, direction string, meterID uint32, intfID uint32, onuID uint32, uniID uint32, tpID uint32) error {
3519 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, intfID, onuID, uniID, tpID)
3520 if err != nil {
3521 return olterrors.NewErrNotFound("meter",
3522 log.Fields{"intf-id": intfID,
3523 "onu-id": onuID,
3524 "uni-id": uniID,
3525 "device-id": f.deviceHandler.device.Id}, err)
3526 }
3527
3528 if meterInfo != nil {
3529 // If RefCnt become 0 clear the meter information from the DB.
3530 if meterInfo.MeterID != meterID && meterInfo.RefCnt == 0 {
3531 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, intfID, onuID, uniID, tpID); err != nil {
3532 return err
3533 }
3534 } else if meterInfo.MeterID != meterID {
3535 logger.Errorw(ctx, "meter-mismatch-for-direction",
3536 log.Fields{"direction": direction,
3537 "kv-store-meter-id": meterInfo.MeterID,
3538 "meter-id-in-flow": meterID,
3539 "device-id": f.deviceHandler.device.Id})
3540 return olterrors.NewErrInvalidValue(log.Fields{
3541 "unsupported": "meter-id",
3542 "kv-store-meter-id": meterInfo.MeterID,
3543 "meter-id-in-flow": meterID,
3544 "device-id": f.deviceHandler.device.Id}, nil)
3545 }
3546 }
3547 return nil
3548}