blob: 1f6574454c65463f42e1c5f36f1586c4b8aa4da0 [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
Matteo Scandolo6056e822019-11-13 14:05:29 -080022 "encoding/hex"
Girish Gowdracefae192020-03-19 18:14:10 -070023 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "fmt"
Gamze Abaka7650be62021-02-26 10:50:36 +000025 "strconv"
serkant.uluderya4aff1862020-09-17 23:35:26 +030026 "strings"
27 "sync"
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070028 "time"
serkant.uluderya4aff1862020-09-17 23:35:26 +030029
khenaidoo106c61a2021-08-11 18:05:46 -040030 "github.com/opencord/voltha-lib-go/v7/pkg/meters"
Mahir Gunyel199570a2021-07-04 15:39:36 -070031
khenaidoo106c61a2021-08-11 18:05:46 -040032 "github.com/opencord/voltha-lib-go/v7/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070034 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040035 tp "github.com/opencord/voltha-lib-go/v7/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080036 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040037 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040038 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040039 ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
40 openoltpb2 "github.com/opencord/voltha-protos/v5/go/openolt"
41 tp_pb "github.com/opencord/voltha-protos/v5/go/tech_profile"
42 "github.com/opencord/voltha-protos/v5/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040043
Thomas Lee S94109f12020-03-03 16:39:29 +053044 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000045 "google.golang.org/grpc/codes"
46 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053047)
48
49const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070050 //IPProtoDhcp flow category
51 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Girish Gowdraa09aeab2020-09-14 16:30:52 -070053 //IgmpProto proto value
54 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070055
56 //EapEthType eapethtype value
57 EapEthType = 0x888e
58 //LldpEthType lldp ethtype value
59 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000060 //IPv4EthType IPv4 ethernet type value
61 IPv4EthType = 0x800
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030062 //PPPoEDEthType PPPoE discovery ethernet type value
63 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070064
Andrea Campanella7acc0b92020-02-14 09:20:49 +010065 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
66 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040067
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068 //DefaultMgmtVlan default vlan value
69 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053070
manikkaraj kbf256be2019-03-25 00:13:48 +053071 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070072
David K. Bainbridge82efc492019-09-04 09:57:11 -070073 //Upstream constant
74 Upstream = "upstream"
75 //Downstream constant
76 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000077 //Multicast constant
78 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070079 //PacketTagType constant
80 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070081 //Untagged constant
82 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070083 //SingleTag constant
84 SingleTag = "single_tag"
85 //DoubleTag constant
86 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053087
88 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089
90 //EthType constant
91 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000092 //EthDst constant
93 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070094 //TPID constant
95 TPID = "tpid"
96 //IPProto constant
97 IPProto = "ip_proto"
98 //InPort constant
99 InPort = "in_port"
100 //VlanVid constant
101 VlanVid = "vlan_vid"
102 //VlanPcp constant
103 VlanPcp = "vlan_pcp"
104
105 //UDPDst constant
106 UDPDst = "udp_dst"
107 //UDPSrc constant
108 UDPSrc = "udp_src"
109 //Ipv4Dst constant
110 Ipv4Dst = "ipv4_dst"
111 //Ipv4Src constant
112 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700113 //Metadata constant
114 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700115 //TunnelID constant
116 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700117 //Output constant
118 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000119 //GroupID constant
120 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700121 // Actions
122
123 //PopVlan constant
124 PopVlan = "pop_vlan"
125 //PushVlan constant
126 PushVlan = "push_vlan"
127 //TrapToHost constant
128 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400129 //MaxMeterBand constant
130 MaxMeterBand = 2
131 //VlanPCPMask contant
132 VlanPCPMask = 0xFF
133 //VlanvIDMask constant
134 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000135 //IntfID constant
136 IntfID = "intfId"
137 //OnuID constant
138 OnuID = "onuId"
139 //UniID constant
140 UniID = "uniId"
141 //PortNo constant
142 PortNo = "portNo"
143 //AllocID constant
144 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000145 //GemID constant
146 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000147
148 //NoneOnuID constant
149 NoneOnuID = -1
150 //NoneUniID constant
151 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700152
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700153 // Max number of flows that can be queued per ONU
154 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530155
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700156 bitMapPrefix = "0b"
157 pbit1 = '1'
158)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400159
Gamze Abakafee36392019-10-03 11:17:24 +0000160type schedQueue struct {
161 direction tp_pb.Direction
162 intfID uint32
163 onuID uint32
164 uniID uint32
165 tpID uint32
166 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700167 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000168 meterID uint32
khenaidoodc2116e2021-10-19 17:33:19 -0400169 flowMetadata *ofp.FlowMetadata
Gamze Abakafee36392019-10-03 11:17:24 +0000170}
171
Gamze Abaka7650be62021-02-26 10:50:36 +0000172type flowContext struct {
173 intfID uint32
174 onuID uint32
175 uniID uint32
176 portNo uint32
177 classifier map[string]interface{}
178 action map[string]interface{}
179 logicalFlow *ofp.OfpFlowStats
180 allocID uint32
181 gemPortID uint32
182 tpID uint32
183 pbitToGem map[uint32]uint32
184 gemToAes map[uint32]bool
185}
186
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700187// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
188// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
189// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
190// flow and processes it serially
191type flowControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400192 ctx context.Context // Flow handler context
193 addFlow bool // if true flow to be added, else removed
194 flow *ofp.OfpFlowStats // Flow message
195 flowMetadata *ofp.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
196 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000197}
198
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700199//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530200type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700201 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700202 techprofile tp.TechProfileIf
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700203 deviceHandler *DeviceHandler
204 grpMgr *OpenOltGroupMgr
205 resourceMgr *rsrcMgr.OpenOltResourceMgr
206
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700207 gemToFlowIDs map[uint32][]uint64 // gem port id to flow ids
208 gemToFlowIDsKey sync.RWMutex // lock to be used to access the gemToFlowIDs map
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700209
210 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
211 packetInGemPortLock sync.RWMutex
212
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700213 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700214 onuGemInfoMap map[uint32]*rsrcMgr.OnuGemInfo //onu, gem and uni info local cache -> map of onuID to OnuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700215 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700216 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700217
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700218 flowIDToGems map[uint64][]uint32
219 flowIDToGemsLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700220
221 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
222 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700223 incomingFlows []chan flowControlBlock
224 stopFlowHandlerRoutine []chan bool
225 flowHandlerRoutineActive []bool
manikkaraj kbf256be2019-03-25 00:13:48 +0530226}
227
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700228//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700229func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000230 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530231 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530232 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530233
manikkaraj kbf256be2019-03-25 00:13:48 +0530234 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700235 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700236 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530237 flowMgr.resourceMgr = rMgr
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700238 if err = flowMgr.populateTechProfileForCurrentPonPort(ctx); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700239 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530240 return nil
241 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700242 flowMgr.gemToFlowIDs = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530243 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700244 flowMgr.flowIDToGems = make(map[uint64][]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700245
246 // Create a slice of buffered channels for handling concurrent flows per ONU.
247 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700248 flowMgr.incomingFlows = make([]chan flowControlBlock, plt.MaxOnusPerPon+1)
249 flowMgr.stopFlowHandlerRoutine = make([]chan bool, plt.MaxOnusPerPon+1)
250 flowMgr.flowHandlerRoutineActive = make([]bool, plt.MaxOnusPerPon+1)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700251 for i := range flowMgr.incomingFlows {
252 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
Girish Gowdraae56c722021-11-22 14:31:11 -0800253 flowMgr.stopFlowHandlerRoutine[i] = make(chan bool)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700254 // Spin up a go routine to handling incoming flows (add/remove).
255 // There will be on go routine per ONU.
256 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700257 flowMgr.flowHandlerRoutineActive[i] = true
258 go flowMgr.perOnuFlowHandlerRoutine(i, flowMgr.incomingFlows[i], flowMgr.stopFlowHandlerRoutine[i])
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700259 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700260 flowMgr.onuGemInfoMap = make(map[uint32]*rsrcMgr.OnuGemInfo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530261 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700262 onuIDStart := flowMgr.deviceHandler.deviceInfo.OnuIdStart
263 onuIDEnd := flowMgr.deviceHandler.deviceInfo.OnuIdEnd
264 for onuID := onuIDStart; onuID <= onuIDEnd; onuID++ {
265 // check for a valid serial number in onuGem as GetOnuGemInfo can return nil error in case of nothing found in the path.
Gamze Abaka6f345c12021-09-08 01:14:33 +0000266 onugem, err := rMgr.GetOnuGemInfo(ctx, ponPortIdx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700267 if err == nil && onugem != nil && onugem.SerialNumber != "" {
268 flowMgr.onuGemInfoMap[onuID] = onugem
269 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530270 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700271
272 //Load flowID list per gem map And gemIDs per flow per interface from the kvstore.
273 flowMgr.loadFlowIDsForGemAndGemIDsForFlow(ctx)
274
Esin Karamanccb714b2019-11-29 15:02:06 +0000275 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700276 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000277 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530278 return &flowMgr
279}
280
Kent Hagermane6ff1012020-07-14 15:07:53 -0400281func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700282 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
283 // Flow is not replicated in this case, we need to register the flow for a single gem-port
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700284 return f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700285 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
286 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
287 for _, gemPort := range deviceFlow.PbitToGemport {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700288 if err := f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700289 return err
290 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700291 }
Gamze Abakafee36392019-10-03 11:17:24 +0000292 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700293 return nil
294}
295
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700296func (f *OpenOltFlowMgr) registerFlowIDForGemAndGemIDForFlow(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
297 // update gem->flows map
298 f.gemToFlowIDsKey.Lock()
299 flowIDList, ok := f.gemToFlowIDs[gemPortID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700300 if !ok {
301 flowIDList = []uint64{flowFromCore.Id}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700302 } else {
303 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700304 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700305 f.gemToFlowIDs[gemPortID] = flowIDList
306 f.gemToFlowIDsKey.Unlock()
307
308 // update flow->gems map
309 f.flowIDToGemsLock.Lock()
310 if _, ok := f.flowIDToGems[flowFromCore.Id]; !ok {
311 f.flowIDToGems[flowFromCore.Id] = []uint32{gemPortID}
312 } else {
313 f.flowIDToGems[flowFromCore.Id] = appendUnique32bit(f.flowIDToGems[flowFromCore.Id], gemPortID)
314 }
315 f.flowIDToGemsLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700316
317 // update the flowids for a gem to the KVstore
318 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400319}
320
Girish Gowdra9602eb42020-09-09 15:50:39 -0700321func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000322 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
khenaidoodc2116e2021-10-19 17:33:19 -0400323 UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000324 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530325 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700326 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530327
Neha Sharma96b7bf22020-06-15 10:37:32 +0000328 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530329 "device-id": f.deviceHandler.device.Id,
330 "intf-id": intfID,
331 "onu-id": onuID,
332 "uni-id": uniID,
333 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700334 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530335 "action": actionInfo,
336 "usmeter-iD": UsMeterID,
337 "dsmeter-iD": DsMeterID,
338 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400339 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
340 // is because the flow is an NNI flow and there would be no onu resources associated with it
341 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400342 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200343 cause := "no-onu-id-for-flow"
344 fields := log.Fields{
345 "onu": onuID,
346 "port-no": portNo,
347 "classifer": classifierInfo,
348 "action": actionInfo,
349 "device-id": f.deviceHandler.device.Id}
350 logger.Errorw(ctx, cause, fields)
351 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530352 }
353
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700354 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000355 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530356 "uni": uni,
357 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530358
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700359 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
360 "device-id": f.deviceHandler.device.Id,
361 "intf-id": intfID,
362 "onu-id": onuID,
363 "uni-id": uniID,
364 "port-no": portNo,
365 "classifier": classifierInfo,
366 "action": actionInfo,
367 "usmeter-id": UsMeterID,
368 "dsmeter-id": DsMeterID,
369 "tp-id": TpID})
370 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
371 if allocID == 0 || gemPorts == nil || TpInst == nil {
372 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
373 return olterrors.NewErrNotFound(
374 "alloc-id-gem-ports-tp-unavailable",
375 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400376 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700377 args := make(map[string]uint32)
378 args[IntfID] = intfID
379 args[OnuID] = onuID
380 args[UniID] = uniID
381 args[PortNo] = portNo
382 args[AllocID] = allocID
383
384 /* Flows can be added specific to gemport if p-bits are received.
385 * If no pbit mentioned then adding flows for all gemports
386 */
Gamze Abaka6d0a64f2021-11-18 08:08:33 +0000387 return f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530388}
389
salmansiddiqui7ac62132019-08-22 03:58:50 +0000390// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530391func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400392
Neha Sharma96b7bf22020-06-15 10:37:32 +0000393 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530394 log.Fields{"dir": sq.direction,
395 "intf-id": sq.intfID,
396 "onu-id": sq.onuID,
397 "uni-id": sq.uniID,
398 "tp-id": sq.tpID,
399 "meter-id": sq.meterID,
400 "tp-inst": sq.tpInst,
401 "flowmetadata": sq.flowMetadata,
402 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400403
Gamze Abakafee36392019-10-03 11:17:24 +0000404 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000405 if err != nil {
406 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400407 }
408
409 /* Lets make a simple assumption that if the meter-id is present on the KV store,
410 * then the scheduler and queues configuration is applied on the OLT device
411 * in the given direction.
412 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000413
Manikkaraj kb1d51442019-07-23 10:41:02 -0400414 var SchedCfg *tp_pb.SchedulerConfig
Girish Gowdraa482f272021-03-24 23:04:19 -0700415 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400416 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530417 return olterrors.NewErrNotFound("meter",
418 log.Fields{"intf-id": sq.intfID,
419 "onu-id": sq.onuID,
420 "uni-id": sq.uniID,
421 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400422 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000423
Girish Gowdraa482f272021-03-24 23:04:19 -0700424 if meterInfo != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +0000425 // If RefCnt become 0 clear the meter information from the DB.
426 if meterInfo.MeterID != sq.meterID && meterInfo.RefCnt == 0 {
427 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID); err != nil {
Girish Gowdraa482f272021-03-24 23:04:19 -0700428 return err
429 }
Gamze Abaka745ccb72021-11-18 11:29:58 +0000430 } else {
431 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id, "meter-id": sq.meterID})
432 if meterInfo.MeterID == sq.meterID {
433 return f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true)
434 }
435 return olterrors.NewErrInvalidValue(log.Fields{
436 "unsupported": "meter-id",
437 "kv-store-meter-id": meterInfo.MeterID,
438 "meter-id-in-flow": sq.meterID,
439 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400440 }
441 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000442
Neha Sharma96b7bf22020-06-15 10:37:32 +0000443 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530444 log.Fields{
445 "meter-id": sq.meterID,
446 "direction": Direction,
447 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000448
Gamze Abakafee36392019-10-03 11:17:24 +0000449 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700450 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Gamze Abakafee36392019-10-03 11:17:24 +0000451 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700452 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Girish Kumar8f73fe02019-12-09 13:19:37 +0000453 }
454
Girish Gowdraa482f272021-03-24 23:04:19 -0700455 found := false
456 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000457 if sq.flowMetadata != nil {
458 for _, meter := range sq.flowMetadata.Meters {
459 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700460 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700461 meterInfo.RefCnt = 1 // initialize it to 1, since this is the first flow that referenced the meter id.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000462 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700463 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530464 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700465 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400466 break
467 }
468 }
469 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000470 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400471 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700472 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530473 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800474 "reason": "Could-not-get-meterbands-from-flowMetadata",
475 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530476 "meter-id": sq.meterID,
477 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478 }
Gamze Abaka01174422021-03-10 06:55:27 +0000479
480 var TrafficShaping *tp_pb.TrafficShapingInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700481 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
Gamze Abaka01174422021-03-10 06:55:27 +0000482 return olterrors.NewErrInvalidValue(log.Fields{
483 "reason": "invalid-meter-config",
484 "meter-id": sq.meterID,
485 "device-id": f.deviceHandler.device.Id}, nil)
486 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400487
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700488 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000489 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400490
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700491 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530492 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
493 log.Fields{"intf-id": sq.intfID,
494 "direction": sq.direction,
495 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400496 }
497
salmansiddiqui7ac62132019-08-22 03:58:50 +0000498 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400499 * store the meter id on the KV store, for further reference.
500 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700501 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530502 return olterrors.NewErrAdapter("failed-updating-meter-id",
503 log.Fields{"onu-id": sq.onuID,
504 "meter-id": sq.meterID,
505 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400506 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000507 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530508 log.Fields{"direction": Direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700509 "meter-info": meterInfo,
510 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400511 return nil
512}
513
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700514func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700515 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000516
517 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530518 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
519 log.Fields{"intf-id": sq.intfID,
520 "direction": sq.direction,
521 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000522 }
523
Gamze Abakacb0e6772021-06-10 08:32:12 +0000524 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
525 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
526 log.Fields{
527 "direction": sq.direction,
528 "TrafficScheds": TrafficSched,
529 "device-id": f.deviceHandler.device.Id,
530 "intfID": sq.intfID,
531 "onuID": sq.onuID,
532 "uniID": sq.uniID})
533 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
534 IntfId: sq.intfID, OnuId: sq.onuID,
535 UniId: sq.uniID, PortNo: sq.uniPort,
536 TrafficScheds: TrafficSched}); err != nil {
537 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
538 }
539 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
540 "direction": sq.direction,
541 "traffic-queues": trafficQueues,
542 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000543 }
544
545 // On receiving the CreateTrafficQueues request, the driver should create corresponding
546 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000547 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530548 log.Fields{"direction": sq.direction,
549 "traffic-queues": trafficQueues,
550 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000551 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
552 UniId: sq.uniID, PortNo: sq.uniPort,
553 TrafficQueues: trafficQueues,
554 TechProfileId: TrafficSched[0].TechProfileId}
555 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
556 if len(queues.TrafficQueues) > 1 {
557 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
558 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
559 }
560 f.revertScheduler(ctx, sq, TrafficSched)
Shrey Baid26912972020-04-16 21:02:31 +0530561 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000562 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000563 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530564 "direction": sq.direction,
565 "traffic-queues": trafficQueues,
566 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000567
Esin Karamanccb714b2019-11-29 15:02:06 +0000568 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700569 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000570 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700571 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 +0000572 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
573 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000574 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000575 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700576 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000577 gemPortID: multicastQueuePerPonPort.GemportId,
578 servicePriority: multicastQueuePerPonPort.Priority,
579 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700580 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000581 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400582 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700583 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400584 return err
585 }
Shrey Baid26912972020-04-16 21:02:31 +0530586
Neha Sharma96b7bf22020-06-15 10:37:32 +0000587 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000588 }
589 }
590 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000591 return nil
592}
593
salmansiddiqui7ac62132019-08-22 03:58:50 +0000594// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530595func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400596
597 var Direction string
598 var SchedCfg *tp_pb.SchedulerConfig
599 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000600 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530601 log.Fields{
602 "direction": sq.direction,
603 "intf-id": sq.intfID,
604 "onu-id": sq.onuID,
605 "uni-id": sq.uniID,
606 "uni-port": sq.uniPort,
607 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000608 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700609 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400610 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000611 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700612 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400613 Direction = "downstream"
614 }
615
Girish Gowdraa482f272021-03-24 23:04:19 -0700616 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 -0400617
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700618 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000619 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000620
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700621 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000622 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530623 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
624 log.Fields{
625 "intf-id": sq.intfID,
626 "direction": sq.direction,
627 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000628 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400629
npujarec5762e2020-01-01 14:08:48 +0530630 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000631 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
632 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000633 TrafficQueues: TrafficQueues,
634 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000635 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530636 log.Fields{
637 "intf-id": sq.intfID,
638 "traffic-queues": TrafficQueues,
639 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400640 }
Gamze Abakacb0e6772021-06-10 08:32:12 +0000641 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400642
Gamze Abakacb0e6772021-06-10 08:32:12 +0000643 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
644 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
645 IntfId: sq.intfID, OnuId: sq.onuID,
646 UniId: sq.uniID, PortNo: sq.uniPort,
647 TrafficScheds: TrafficSched}); err != nil {
648 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
649 log.Fields{
650 "intf-id": sq.intfID,
651 "traffic-schedulers": TrafficSched,
652 "onu-id": sq.onuID,
653 "uni-id": sq.uniID,
654 "uni-port": sq.uniPort}, err)
655 }
656
657 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
658 log.Fields{"device-id": f.deviceHandler.device.Id,
659 "intf-id": sq.intfID,
660 "onu-id": sq.onuID,
661 "uni-id": sq.uniID,
662 "uni-port": sq.uniPort})
663
664 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700665 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
Gamze Abakacb0e6772021-06-10 08:32:12 +0000666 // Delete the TCONT on the ONU.
667 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
668 tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
669 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
670 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
671 log.Fields{
672 "intf": sq.intfID,
673 "onu-id": sq.onuID,
674 "uni-id": sq.uniID,
675 "device-id": f.deviceHandler.device.Id,
676 "alloc-id": allocID})
677 }
678 }
679 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000680
681 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400682 * delete the meter id on the KV store.
683 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700684 err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400685 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530686 return olterrors.NewErrAdapter("unable-to-remove-meter",
687 log.Fields{
688 "onu": sq.onuID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700689 "device-id": f.deviceHandler.device.Id,
690 "intf-id": sq.intfID,
691 "onu-id": sq.onuID,
692 "uni-id": sq.uniID,
693 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400694 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000695 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530696 log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530697 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700698 "device-id": f.deviceHandler.device.Id,
699 "intf-id": sq.intfID,
700 "onu-id": sq.onuID,
701 "uni-id": sq.uniID,
702 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400703 return err
704}
705
Girish Gowdra197acc12021-08-16 10:59:45 -0700706// We are trying to force remove the schedulers and queues here if one exists for the given key.
707// We ignore any errors encountered in the process. The errors most likely are encountered when
708// the schedulers and queues are already cleared for the given key.
709func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
710
711 var schedCfg *tp_pb.SchedulerConfig
712 var err error
713 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
714 log.Fields{
715 "direction": sq.direction,
716 "intf-id": sq.intfID,
717 "onu-id": sq.onuID,
718 "uni-id": sq.uniID,
719 "uni-port": sq.uniPort,
720 "tp-id": sq.tpID,
721 "device-id": f.deviceHandler.device.Id})
722 if sq.direction == tp_pb.Direction_UPSTREAM {
723 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
724 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
725 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
726 }
727
728 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
729 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
730 TrafficSched[0].TechProfileId = sq.tpID
731
732 // Remove traffic queues. Ignore any errors, just log them.
733 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
734 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
735 "direction": sq.direction,
736 "intf-id": sq.intfID,
737 "onu-id": sq.onuID,
738 "uni-id": sq.uniID,
739 "uni-port": sq.uniPort,
740 "tp-id": sq.tpID,
741 "device-id": f.deviceHandler.device.Id,
742 "err": err})
743 } else {
744 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
745 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
746 UniId: sq.uniID, PortNo: sq.uniPort,
747 TrafficQueues: TrafficQueues,
748 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
749 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
750 "direction": sq.direction,
751 "intf-id": sq.intfID,
752 "onu-id": sq.onuID,
753 "uni-id": sq.uniID,
754 "uni-port": sq.uniPort,
755 "tp-id": sq.tpID,
756 "device-id": f.deviceHandler.device.Id,
757 "err": err})
758
759 } else {
760 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
761 "direction": sq.direction,
762 "intf-id": sq.intfID,
763 "onu-id": sq.onuID,
764 "uni-id": sq.uniID,
765 "uni-port": sq.uniPort,
766 "tp-id": sq.tpID})
767 }
768 }
769
770 // Remove traffic schedulers. Ignore any errors, just log them.
771 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
772 IntfId: sq.intfID, OnuId: sq.onuID,
773 UniId: sq.uniID, PortNo: sq.uniPort,
774 TrafficScheds: TrafficSched}); err != nil {
775 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
776 "direction": sq.direction,
777 "intf-id": sq.intfID,
778 "onu-id": sq.onuID,
779 "uni-id": sq.uniID,
780 "uni-port": sq.uniPort,
781 "tp-id": sq.tpID,
782 "device-id": f.deviceHandler.device.Id,
783 "err": err})
784 } else {
785 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
786 "direction": sq.direction,
787 "intf-id": sq.intfID,
788 "onu-id": sq.onuID,
789 "uni-id": sq.uniID,
790 "uni-port": sq.uniPort,
791 "tp-id": sq.tpID})
792 }
793}
794
Gamze Abakafee36392019-10-03 11:17:24 +0000795// This function allocates tconts and GEM ports for an ONU
khenaidoodc2116e2021-10-19 17:33:19 -0400796func (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 +0000797 var allocIDs []uint32
798 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530799 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530800 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000801 var err error
npujarec5762e2020-01-01 14:08:48 +0530802 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
803 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000804 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530805
Neha Sharma96b7bf22020-06-15 10:37:32 +0000806 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530807 "intf-id": intfID,
808 "onu-id": onuID,
809 "uni-id": uniID,
810 "device-id": f.deviceHandler.device.Id,
811 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530812
Manikkaraj kb1d51442019-07-23 10:41:02 -0400813 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700814 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000815 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000816 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530817 log.Fields{
818 "path": tpPath,
819 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700820 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000821 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530822 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000823 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530824 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700825 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530826 "tp-id": TpID,
827 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000828 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530829 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400830 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700831 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400832 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530833 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000834 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530835 log.Fields{
836 "uni": uni,
837 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530838 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530839 }
Gamze Abakafee36392019-10-03 11:17:24 +0000840
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700841 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700842 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700843 if UsMeterID != 0 {
844 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
845 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
846 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000847 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700848 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700849 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700850 "onu-id": onuID,
851 "uni-id": uniID,
852 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700853 "meter-id": UsMeterID,
854 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000855 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700856 return 0, nil, nil
857 }
858 }
859 if DsMeterID != 0 {
860 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
861 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
862 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000863 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700864 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700865 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700866 "onu-id": onuID,
867 "uni-id": uniID,
868 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700869 "meter-id": DsMeterID,
870 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000871 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700872 return 0, nil, nil
873 }
874 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700875 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700876 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700877 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700878 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700879 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000880
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700881 if tpInstanceExists {
882 return allocID, gemPortIDs, techProfileInstance
883 }
884
885 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700886 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700887 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000888 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700889 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700890 "intf-id": intfID,
891 "onu-id": onuID,
892 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700893 "alloc-ids": allocIDs,
894 "gemports": allgemPortIDs,
895 "device-id": f.deviceHandler.device.Id})
896 // Send Tconts and GEM ports to KV store
897 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530898 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400899 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700900 // CreateSchedulerQueues for EPON needs to be implemented here
901 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700902 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700903 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700904 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700905 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700906 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700907
908 if tpInstanceExists {
909 return allocID, gemPortIDs, techProfileInstance
910 }
911
912 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700913 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700914 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000915 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700916 log.Fields{
917 "alloc-ids": allocIDs,
918 "gemports": allgemPortIDs,
919 "device-id": f.deviceHandler.device.Id})
920 // Send Tconts and GEM ports to KV store
921 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
922 return allocID, gemPortIDs, techProfileInstance
923 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000924 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700925 log.Fields{
926 "tpInst": tpInst})
927 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530928 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530929}
930
npujarec5762e2020-01-01 14:08:48 +0530931func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530932
Neha Sharma96b7bf22020-06-15 10:37:32 +0000933 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530934 log.Fields{
935 "intf-id": intfID,
936 "onu-id": onuID,
937 "uni-id": uniID,
938 "alloc-id": allocID,
939 "gemport-ids": gemPortIDs,
940 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530941 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530942 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000943 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 +0530944 }
npujarec5762e2020-01-01 14:08:48 +0530945 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000946 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 +0530947 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700948
Neha Sharma96b7bf22020-06-15 10:37:32 +0000949 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 -0400950 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530951 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400952 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530953}
954
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700955func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530956 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000957 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700958 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
959 var err error
960 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
961 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
962 if err != nil || f.techprofile == nil {
963 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
964 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
965 }
966 logger.Debugw(ctx, "init-tech-profile-done",
967 log.Fields{
968 "intf-id": intfID,
969 "device-id": f.deviceHandler.device.Id})
970 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700971 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530972 }
973 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700974 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
975 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 +0530976}
977
Gamze Abaka7650be62021-02-26 10:50:36 +0000978func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Andrea Campanellafaa42152021-10-28 11:50:56 +0530979 flowContext.classifier[PacketTagType] = SingleTag // FIXME: This hardcoding needs to be removed.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000980 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530981 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000982 "uplinkClassifier": flowContext.classifier,
983 "uplinkAction": flowContext.action})
984 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530985 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530986}
987
Gamze Abaka7650be62021-02-26 10:50:36 +0000988func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
989 downlinkClassifier := flowContext.classifier
990 downlinkAction := flowContext.action
991
Andrea Campanellafaa42152021-10-28 11:50:56 +0530992 // TODO: For now mark the PacketTagType as SingleTag when OLT is transparent to VLAN
993 // Per some deployment models, it is also possible that ONU operates on double tagged packets,
994 // so this hardcoding of SingeTag packet-tag-type may be problem for such deployment models.
995 // Need a better way for detection of packet tag type from OpenFlow message.
996 if _, ok := downlinkClassifier[VlanVid]; !ok {
997 downlinkClassifier[PacketTagType] = SingleTag
998 } else {
999 downlinkClassifier[PacketTagType] = DoubleTag
1000 downlinkAction[PopVlan] = true
1001 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001002 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301003 log.Fields{
1004 "downlinkClassifier": downlinkClassifier,
1005 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001006 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
1007 if vlan, exists := downlinkClassifier[VlanVid]; exists {
1008 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -07001009 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001010 if uint32(metadata.(uint64)) == plt.MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001011 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301012 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001013 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301014 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +00001015 "onu-id": flowContext.onuID,
1016 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001017 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -04001018 }
1019 }
1020 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301021 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001022
Matt Jeannereted16b7c2019-11-01 13:31:35 -04001023 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1024 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +05301025 if ok {
1026 downlinkAction[VlanVid] = dlClVid & 0xfff
Girish Gowdra26f344b2019-10-23 14:39:13 +05301027 }
1028
Gamze Abaka7650be62021-02-26 10:50:36 +00001029 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301030}
1031
Gamze Abaka7650be62021-02-26 10:50:36 +00001032func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001033
Gamze Abaka7650be62021-02-26 10:50:36 +00001034 intfID := flowContext.intfID
1035 onuID := flowContext.onuID
1036 uniID := flowContext.uniID
1037 classifier := flowContext.classifier
1038 action := flowContext.action
1039 allocID := flowContext.allocID
1040 gemPortID := flowContext.gemPortID
1041 tpID := flowContext.tpID
1042 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001043 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301044 log.Fields{
1045 "intf-id": intfID,
1046 "onu-id": onuID,
1047 "uni-id": uniID,
1048 "device-id": f.deviceHandler.device.Id,
1049 "classifier": classifier,
1050 "action": action,
1051 "direction": direction,
1052 "alloc-id": allocID,
1053 "gemport-id": gemPortID,
1054 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001055
1056 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001057 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301058 log.Fields{
1059 "device-id": f.deviceHandler.device.Id,
1060 "intf-id": intfID,
1061 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001062 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301063 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001064 classifierProto, err := makeOpenOltClassifierField(classifier)
1065 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301066 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301067 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001068 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301069 log.Fields{
1070 "classifier": *classifierProto,
1071 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001072 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001073 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301074 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301075 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001076 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301077 log.Fields{
1078 "action": *actionProto,
1079 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001080 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301081 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301082 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001083 log.Fields{
1084 "classifier": classifier,
1085 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301086 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001087 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301088 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001089
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001090 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001091 OnuId: int32(onuID),
1092 UniId: int32(uniID),
1093 FlowId: logicalFlow.Id,
1094 FlowType: direction,
1095 AllocId: int32(allocID),
1096 NetworkIntfId: int32(networkIntfID),
1097 GemportId: int32(gemPortID),
1098 Classifier: classifierProto,
1099 Action: actionProto,
1100 Priority: int32(logicalFlow.Priority),
1101 Cookie: logicalFlow.Cookie,
1102 PortNo: flowContext.portNo,
1103 TechProfileId: tpID,
1104 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1105 PbitToGemport: flowContext.pbitToGem,
1106 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001107 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001108 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001109 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301110 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001111 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301112 log.Fields{"direction": direction,
1113 "device-id": f.deviceHandler.device.Id,
1114 "flow": flow,
1115 "intf-id": intfID,
1116 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001117
David K. Bainbridge794735f2020-02-11 21:01:37 -08001118 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301119}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001120
Gamze Abaka7650be62021-02-26 10:50:36 +00001121func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1122
1123 intfID := flowContext.intfID
1124 onuID := flowContext.onuID
1125 uniID := flowContext.uniID
1126 logicalFlow := flowContext.logicalFlow
1127 classifier := flowContext.classifier
1128 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301129
Neha Sharma96b7bf22020-06-15 10:37:32 +00001130 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301131 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301132 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001133 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301134 "action": action,
1135 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001136 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301137 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301138
1139 // Clear the action map
1140 for k := range action {
1141 delete(action, k)
1142 }
1143
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001144 action[TrapToHost] = true
1145 classifier[UDPSrc] = uint32(68)
1146 classifier[UDPDst] = uint32(67)
1147 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301148
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001149 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001150 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301151 log.Fields{
1152 "device-id": f.deviceHandler.device.Id,
1153 "intf-id": intfID,
1154 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001155 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301156 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301157
Neha Sharma96b7bf22020-06-15 10:37:32 +00001158 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301159 log.Fields{
1160 "ul_classifier": classifier,
1161 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001162 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301163 "intf-id": intfID,
1164 "onu-id": onuID,
1165 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301166
David K. Bainbridge794735f2020-02-11 21:01:37 -08001167 classifierProto, err := makeOpenOltClassifierField(classifier)
1168 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301169 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301170 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001171 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001172 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301174 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301175 }
1176
David K. Bainbridge794735f2020-02-11 21:01:37 -08001177 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001178 OnuId: int32(onuID),
1179 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001180 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001181 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001182 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001183 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001184 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301185 Classifier: classifierProto,
1186 Action: actionProto,
1187 Priority: int32(logicalFlow.Priority),
1188 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001189 PortNo: flowContext.portNo,
1190 TechProfileId: flowContext.tpID,
1191 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1192 PbitToGemport: flowContext.pbitToGem,
1193 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001194 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001195 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001196 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001197 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001198 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301199 log.Fields{
1200 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001201 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301202 "intf-id": intfID,
1203 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301204
David K. Bainbridge794735f2020-02-11 21:01:37 -08001205 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301206}
1207
Esin Karamanae41e2b2019-12-17 18:13:13 +00001208//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001209func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1210 delete(flowContext.classifier, VlanVid)
1211 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001212}
1213
1214//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001215func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1216
1217 intfID := flowContext.intfID
1218 onuID := flowContext.onuID
1219 uniID := flowContext.uniID
1220 logicalFlow := flowContext.logicalFlow
1221 classifier := flowContext.classifier
1222 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001223
Neha Sharma96b7bf22020-06-15 10:37:32 +00001224 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001225 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301226 return olterrors.NewErrNotFound("nni-interface-id",
1227 log.Fields{
1228 "classifier": classifier,
1229 "action": action,
1230 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001231 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001232 }
1233
1234 // Clear the action map
1235 for k := range action {
1236 delete(action, k)
1237 }
1238
1239 action[TrapToHost] = true
1240 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001241
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001242 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001243 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001245 }
1246
Neha Sharma96b7bf22020-06-15 10:37:32 +00001247 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301248 log.Fields{
1249 "ul_classifier": classifier,
1250 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001251 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301252 "device-id": f.deviceHandler.device.Id,
1253 "intf-id": intfID,
1254 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001255
David K. Bainbridge794735f2020-02-11 21:01:37 -08001256 classifierProto, err := makeOpenOltClassifierField(classifier)
1257 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301258 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001259 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001260 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301261 log.Fields{
1262 "classifier": *classifierProto,
1263 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001264 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001265 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301266 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001267 }
1268
David K. Bainbridge794735f2020-02-11 21:01:37 -08001269 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001270 OnuId: int32(onuID),
1271 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001272 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001273 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001274 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001275 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001276 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001277 Classifier: classifierProto,
1278 Action: actionProto,
1279 Priority: int32(logicalFlow.Priority),
1280 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001281 PortNo: flowContext.portNo,
1282 TechProfileId: flowContext.tpID,
1283 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1284 PbitToGemport: flowContext.pbitToGem,
1285 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001286 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001287
David K. Bainbridge794735f2020-02-11 21:01:37 -08001288 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001289 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 -08001290 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001291
David K. Bainbridge794735f2020-02-11 21:01:37 -08001292 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001293}
1294
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001295// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001296func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1297 intfID := flowContext.intfID
1298 onuID := flowContext.onuID
1299 uniID := flowContext.uniID
1300 portNo := flowContext.portNo
1301 allocID := flowContext.allocID
1302 gemPortID := flowContext.gemPortID
1303 logicalFlow := flowContext.logicalFlow
1304 classifier := flowContext.classifier
1305 action := flowContext.action
1306
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001307 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301308 log.Fields{
1309 "intf-id": intfID,
1310 "onu-id": onuID,
1311 "port-no": portNo,
1312 "alloc-id": allocID,
1313 "gemport-id": gemPortID,
1314 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001315 "flow": logicalFlow,
1316 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301317
1318 uplinkClassifier := make(map[string]interface{})
1319 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301320
manikkaraj kbf256be2019-03-25 00:13:48 +05301321 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001322 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001323 uplinkClassifier[PacketTagType] = SingleTag
1324 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001325 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301326 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001327 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001328 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001329 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301330 "device-id": f.deviceHandler.device.Id,
1331 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001332 "intf-id": intfID,
1333 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001334 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301335 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001336 //Add Uplink EthType Flow
1337 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301338 log.Fields{
1339 "ul_classifier": uplinkClassifier,
1340 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001341 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301342 "device-id": f.deviceHandler.device.Id,
1343 "intf-id": intfID,
1344 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301345
David K. Bainbridge794735f2020-02-11 21:01:37 -08001346 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1347 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301348 return olterrors.NewErrInvalidValue(log.Fields{
1349 "classifier": uplinkClassifier,
1350 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301351 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001352 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301353 log.Fields{
1354 "classifier": *classifierProto,
1355 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001356 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001357 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301358 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301359 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001360 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301361 log.Fields{
1362 "action": *actionProto,
1363 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001364 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301365 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301366 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001367 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301368 "action": action,
1369 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001370 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301371 }
1372
David K. Bainbridge794735f2020-02-11 21:01:37 -08001373 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001374 OnuId: int32(onuID),
1375 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001376 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001377 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001378 AllocId: int32(allocID),
1379 NetworkIntfId: int32(networkIntfID),
1380 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301381 Classifier: classifierProto,
1382 Action: actionProto,
1383 Priority: int32(logicalFlow.Priority),
1384 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001385 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001386 TechProfileId: flowContext.tpID,
1387 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1388 PbitToGemport: flowContext.pbitToGem,
1389 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001390 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001391 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001392 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001393 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001394 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301395 log.Fields{
1396 "device-id": f.deviceHandler.device.Id,
1397 "onu-id": onuID,
1398 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001399 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301400 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001401
David K. Bainbridge794735f2020-02-11 21:01:37 -08001402 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301403}
1404
David K. Bainbridge794735f2020-02-11 21:01:37 -08001405func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001406 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001407
1408 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1409 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1410 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001411 if vlanID != ReservedVlan {
1412 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001413 classifier.OVid = vid
1414 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301415 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301416 // 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 -07001417 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1418 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301419 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1420 // If OLT is using transparent tag mechanism, then it classifies whatever tag it sees to/from ONU which
1421 //is OVid from the perspective of the OLT. When OLT also places or pops the outer tag, then classifierInfo[Metadata]
1422 // becomes the IVid.
1423 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1424 if vid != ReservedVlan {
1425 classifier.IVid = vid
1426 }
1427 } else {
1428 if vid != ReservedVlan {
1429 classifier.OVid = vid
1430 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001431 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301432 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301433 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001434 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301435 classifier.OPbits = vlanPcp
1436 } else {
1437 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301438 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001439 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1440 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1441 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1442 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001443 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001444 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1445 classifier.PktTagType = pktTagType
1446
1447 switch pktTagType {
1448 case SingleTag:
1449 case DoubleTag:
1450 case Untagged:
1451 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001452 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301453 }
1454 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001455 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301456}
1457
Gamze Abaka724d0852020-03-18 12:10:24 +00001458func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001459 var actionCmd openoltpb2.ActionCmd
1460 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301461 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001462 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301463 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001464 if _, ok := actionInfo[VlanPcp]; ok {
1465 action.Cmd.RemarkInnerPbits = true
1466 action.IPbits = actionInfo[VlanPcp].(uint32)
1467 if _, ok := actionInfo[VlanVid]; ok {
1468 action.Cmd.TranslateInnerTag = true
1469 action.IVid = actionInfo[VlanVid].(uint32)
1470 }
1471 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001472 } else if _, ok := actionInfo[PushVlan]; ok {
1473 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301474 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001475 if _, ok := actionInfo[VlanPcp]; ok {
1476 action.OPbits = actionInfo[VlanPcp].(uint32)
1477 action.Cmd.RemarkOuterPbits = true
1478 if _, ok := classifierInfo[VlanVid]; ok {
1479 action.IVid = classifierInfo[VlanVid].(uint32)
1480 action.Cmd.TranslateInnerTag = true
1481 }
1482 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001483 } else if _, ok := actionInfo[TrapToHost]; ok {
1484 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301485 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301486 // When OLT is transparent to vlans no-action is valid.
1487 /*
1488 else {
1489 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1490 }
1491 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001492 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301493}
1494
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001495// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001496func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001497 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301498}
1499
Gamze Abakafee36392019-10-03 11:17:24 +00001500// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001501// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1502// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1503// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1504// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1505// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1506// because it was observed that if the ONU device was deleted too soon after the flows were
1507// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1508// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1509// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001510func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301511 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001512 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1513
Gamze Abakafee36392019-10-03 11:17:24 +00001514 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001515
1516 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001517 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001518 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1519 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
1520 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1521 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1522 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1523 log.Fields{
1524 "tp-id": tpID,
1525 "path": tpPath})
1526 }
1527 switch tpInstance := tpInst.(type) {
1528 case *tp_pb.TechProfileInstance:
1529 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1530 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1531 }
1532 // Force cleanup scheduler/queues -- end
1533
1534 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301535 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001536 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301537 // return err
1538 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001539 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001540 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 +00001541 }
1542 return nil
1543}
1544
1545// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301546func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001547 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001548 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001549 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001550 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301551 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1552 log.Fields{
1553 "tp-id": tpID,
1554 "uni-port-name": uniPortName,
1555 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001556 }
1557 return nil
1558}
1559
David K. Bainbridge794735f2020-02-11 21:01:37 -08001560func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001561
1562 var intfID uint32
1563 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1564 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1565 */
1566 if deviceFlow.AccessIntfId != -1 {
1567 intfID = uint32(deviceFlow.AccessIntfId)
1568 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001569 // We need to log the valid interface ID.
1570 // 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 +00001571 intfID = uint32(deviceFlow.NetworkIntfId)
1572 }
1573
Neha Sharma96b7bf22020-06-15 10:37:32 +00001574 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301575 "flow": *deviceFlow,
1576 "device-id": f.deviceHandler.device.Id,
1577 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001578 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001579
1580 st, _ := status.FromError(err)
1581 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001582 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001583 "err": err,
1584 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301585 "device-id": f.deviceHandler.device.Id,
1586 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001587 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301588 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001589
1590 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001591 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301592 log.Fields{"err": err,
1593 "device-flow": deviceFlow,
1594 "device-id": f.deviceHandler.device.Id,
1595 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001596 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001597 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001598 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301599 log.Fields{
1600 "flow": *deviceFlow,
1601 "device-id": f.deviceHandler.device.Id,
1602 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001603
1604 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1605 if deviceFlow.AccessIntfId != -1 {
1606 // No need to register the flow if it is a trap on nni flow.
1607 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1608 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1609 return err
1610 }
1611 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001612 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001613}
1614
Neha Sharma96b7bf22020-06-15 10:37:32 +00001615func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1616 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301617 log.Fields{
1618 "flow": *deviceFlow,
1619 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001620 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001621 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001622 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001623 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301624 log.Fields{
1625 "err": err,
1626 "deviceFlow": deviceFlow,
1627 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001628 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001629 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001630 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001631 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001632
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001633 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001634 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001635 "of-flow-id": ofFlowID,
1636 "flow": *deviceFlow,
1637 "device-id": f.deviceHandler.device.Id,
1638 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001639 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301640}
1641
David K. Bainbridge794735f2020-02-11 21:01:37 -08001642func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001643
1644 classifierInfo := make(map[string]interface{})
1645 actionInfo := make(map[string]interface{})
1646
1647 classifierInfo[EthType] = uint32(LldpEthType)
1648 classifierInfo[PacketTagType] = Untagged
1649 actionInfo[TrapToHost] = true
1650
1651 // LLDP flow is installed to trap LLDP packets on the NNI port.
1652 // We manage flow_id resource pool on per PON port basis.
1653 // Since this situation is tricky, as a hack, we pass the NNI port
1654 // index (network_intf_id) as PON port Index for the flow_id resource
1655 // pool. Also, there is no ONU Id available for trapping LLDP packets
1656 // on NNI port, use onu_id as -1 (invalid)
1657 // ****************** CAVEAT *******************
1658 // This logic works if the NNI Port Id falls within the same valid
1659 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1660 // we need to have a re-look at this.
1661 // *********************************************
1662
1663 var onuID = -1
1664 var uniID = -1
1665 var gemPortID = -1
1666
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001667 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001668 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301669 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001670 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001671 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001672 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001673 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001674 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001675
David K. Bainbridge794735f2020-02-11 21:01:37 -08001676 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1677 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301678 return olterrors.NewErrInvalidValue(
1679 log.Fields{
1680 "classifier": classifierInfo,
1681 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001682 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001683 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301684 log.Fields{
1685 "classifier": *classifierProto,
1686 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001687 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001688 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301689 return olterrors.NewErrInvalidValue(
1690 log.Fields{
1691 "action": actionInfo,
1692 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001693 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001694 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301695 log.Fields{
1696 "action": *actionProto,
1697 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001698
1699 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1700 OnuId: int32(onuID), // OnuId not required
1701 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001702 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001703 FlowType: Downstream,
1704 NetworkIntfId: int32(networkInterfaceID),
1705 GemportId: int32(gemPortID),
1706 Classifier: classifierProto,
1707 Action: actionProto,
1708 Priority: int32(flow.Priority),
1709 Cookie: flow.Cookie,
1710 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001711 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001712 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301713 log.Fields{
1714 "flow": downstreamflow,
1715 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001716 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001717 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301718 log.Fields{
1719 "device-id": f.deviceHandler.device.Id,
1720 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001721 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001722
David K. Bainbridge794735f2020-02-11 21:01:37 -08001723 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301724}
1725
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001726func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1727 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001728}
1729
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001730//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001731func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001732 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1733 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1734 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001735 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301736 log.Fields{
1737 "intf-id": intfID,
1738 "onu-id": onuID,
1739 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001740 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001741 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301742 return nil, olterrors.NewErrNotFound("onu-child-device",
1743 log.Fields{
1744 "onu-id": onuID,
1745 "intf-id": intfID,
1746 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001747 }
khenaidoo106c61a2021-08-11 18:05:46 -04001748 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 -07001749 //better to ad the device to cache here.
1750 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1751 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001752 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301753 log.Fields{
1754 "intf-id": intfID,
1755 "onu-id": onuID,
1756 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001757 }
1758
1759 return onuDev.(*OnuDevice), nil
1760}
1761
1762//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001763func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1764 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301765 log.Fields{
1766 "pon-port": intfID,
1767 "onu-id": onuID,
1768 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001769 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001770 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001771 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301772 return nil, olterrors.NewErrNotFound("onu",
1773 log.Fields{
1774 "interface-id": parentPortNo,
1775 "onu-id": onuID,
1776 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001777 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301778 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001779 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301780 log.Fields{
1781 "device-id": f.deviceHandler.device.Id,
1782 "child_device_id": onuDevice.Id,
1783 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301784 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301785}
1786
Neha Sharma96b7bf22020-06-15 10:37:32 +00001787func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1788 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301789 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001790 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301791 log.Fields{
1792 "intf-id": intfID,
1793 "onu-id": onuID,
1794 "uni-id": uniID,
1795 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001796 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301797 }
1798
khenaidoodc2116e2021-10-19 17:33:19 -04001799 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001800 DeviceId: onuDev.deviceID,
1801 UniId: uniID,
1802 TpInstancePath: tpPath,
1803 GemPortId: gemPortID,
1804 }
1805 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1806
1807 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301808 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1809 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001810 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1811 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301812 "onu-id": onuDev.deviceID,
1813 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001814 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301815 }
khenaidoo106c61a2021-08-11 18:05:46 -04001816
Neha Sharma96b7bf22020-06-15 10:37:32 +00001817 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301818 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001819 "msg": delGemPortMsg,
1820 "from-adapter": f.deviceHandler.device.Type,
1821 "to-adapter": onuDev.deviceType,
1822 "device-id": f.deviceHandler.device.Id,
1823 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301824 return nil
1825}
1826
Neha Sharma96b7bf22020-06-15 10:37:32 +00001827func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1828 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301829 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001830 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301831 log.Fields{
1832 "intf-id": intfID,
1833 "onu-id": onuID,
1834 "uni-id": uniID,
1835 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001836 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301837 }
1838
khenaidoodc2116e2021-10-19 17:33:19 -04001839 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001840 DeviceId: onuDev.deviceID,
1841 UniId: uniID,
1842 TpInstancePath: tpPath,
1843 AllocId: allocID,
1844 }
1845
Neha Sharma96b7bf22020-06-15 10:37:32 +00001846 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301847 log.Fields{
1848 "msg": *delTcontMsg,
1849 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001850
1851 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301852 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1853 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001854 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1855 "to-adapter": onuDev.adapterEndpoint,
1856 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301857 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001858 "device-id": f.deviceHandler.device.Id}, err)
1859
Girish Gowdra6b130582019-11-20 16:45:20 +05301860 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001861 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301862 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001863 "msg": delTcontMsg,
1864 "device-id": f.deviceHandler.device.Id,
1865 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301866 return nil
1867}
1868
Girish Gowdrac3037402020-01-22 20:29:53 +05301869// Once the gemport is released for a given onu, it also has to be cleared from local cache
1870// which was used for deriving the gemport->logicalPortNo during packet-in.
1871// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1872// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001873func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001874 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301875 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001876 "gem-port-id": gemPortID,
1877 "intf-id": intfID,
1878 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001879 "device-id": f.deviceHandler.device.Id})
1880 f.onuGemInfoLock.RLock()
1881 onugem, ok := f.onuGemInfoMap[onuID]
1882 f.onuGemInfoLock.RUnlock()
1883 if !ok {
1884 logger.Warnw(ctx, "onu gem info already cleared from cache", log.Fields{
1885 "gem-port-id": gemPortID,
1886 "intf-id": intfID,
1887 "onu-id": onuID,
1888 "device-id": f.deviceHandler.device.Id})
1889 return
1890 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001891deleteLoop:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001892 for j, gem := range onugem.GemPorts {
1893 // If the gemport is found, delete it from local cache.
1894 if gem == gemPortID {
1895 onugem.GemPorts = append(onugem.GemPorts[:j], onugem.GemPorts[j+1:]...)
1896 f.onuGemInfoLock.Lock()
1897 f.onuGemInfoMap[onuID] = onugem
1898 f.onuGemInfoLock.Unlock()
1899 logger.Infow(ctx, "removed-gemport-from-local-cache",
1900 log.Fields{
1901 "intf-id": intfID,
1902 "onu-id": onuID,
1903 "deletedgemport-id": gemPortID,
1904 "gemports": onugem.GemPorts,
1905 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001906 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301907 }
1908 }
1909}
1910
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301911//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001912// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001913func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Gamze Abaka411ef2f2021-11-22 08:38:08 +00001914 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001915
1916 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001917
Girish Gowdraa482f272021-03-24 23:04:19 -07001918 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1919 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001920 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1921 log.Fields{
1922 "tpPath": tpPath,
1923 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001924
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001925 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001926 if err != nil || techprofileInst == nil {
1927 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1928 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1929 if childDevice == nil {
1930 // happens when subscriber un-provision is immediately followed by child device delete
1931 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1932 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1933 return nil
1934 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001935 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1936 log.Fields{
1937 "tp-id": tpID,
1938 "path": tpPath}, err)
1939 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001940
1941 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001942 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001943 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001944 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1945 gemPortID := gemPort.GemportId
1946 used := f.isGemPortUsedByAnotherFlow(gemPortID, flowID)
1947 if used {
1948 f.gemToFlowIDsKey.RLock()
1949 flowIDs := f.gemToFlowIDs[gemPortID]
1950 f.gemToFlowIDsKey.RUnlock()
1951
1952 for i, flowIDinMap := range flowIDs {
1953 if flowIDinMap == flowID {
1954 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1955 f.gemToFlowIDsKey.Lock()
1956 f.gemToFlowIDs[gemPortID] = flowIDs
1957 f.gemToFlowIDsKey.Unlock()
1958 // everytime gemToFlowIDs cache is updated the same should be updated
1959 // in kv store by calling UpdateFlowIDsForGem
1960 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, gemPortID, flowIDs); err != nil {
1961 return err
1962 }
1963 break
1964 }
1965 }
1966 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1967 log.Fields{
1968 "gemport-id": gemPortID,
1969 "usedByFlows": flowIDs,
1970 "currentFlow": flowID,
1971 "device-id": f.deviceHandler.device.Id})
1972 allGemPortsFree = false
1973 }
1974 }
1975 if !allGemPortsFree {
1976 return nil
1977 }
1978 }
1979
1980 logger.Debugw(ctx, "all-gem-ports-are-free-to-be-deleted", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
1981 switch techprofileInst := techprofileInst.(type) {
1982 case *tp_pb.TechProfileInstance:
1983 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
1984 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQueue)
1985 if !allocExists {
Girish Gowdraa482f272021-03-24 23:04:19 -07001986 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001987 logger.Warn(ctx, err)
1988 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001989 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001990 logger.Warn(ctx, err)
1991 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001992
1993 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
1994 if err := f.RemoveSchedulerQueues(ctx, schedQueue); err != nil {
1995 logger.Warn(ctx, err)
1996 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001997 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001998 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId)
1999
2000 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
2001 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
2002 if err := f.RemoveSchedulerQueues(ctx, schedQueue); err != nil {
2003 logger.Warn(ctx, err)
2004 }
2005 }
2006
2007 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2008 gemPortID := gemPort.GemportId
2009 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), gemPortID)
2010 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), gemPortID) // ignore error and proceed.
2011
2012 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gemPortID); err == nil {
2013 //everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
2014 // by calling DeleteFlowIDsForGem
2015 f.gemToFlowIDsKey.Lock()
2016 delete(f.gemToFlowIDs, gemPortID)
2017 f.gemToFlowIDsKey.Unlock()
2018 } else {
2019 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
2020 log.Fields{
2021 "err": err,
2022 "intf": intfID,
2023 "onu-id": onuID,
2024 "uni-id": uniID,
2025 "device-id": f.deviceHandler.device.Id,
2026 "gemport-id": gemPortID})
2027 }
2028
2029 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), gemPortID)
2030
2031 // Delete the gem port on the ONU.
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002032 if sendDeleteGemRequest {
2033 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPortID, tpPath); err != nil {
2034 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2035 log.Fields{
2036 "err": err,
2037 "intfID": intfID,
2038 "onu-id": onuID,
2039 "uni-id": uniID,
2040 "device-id": f.deviceHandler.device.Id,
2041 "gemport-id": gemPortID})
2042 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00002043 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002044 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002045 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002046 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07002047 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002048 logger.Warn(ctx, err)
2049 }
Girish Gowdraa482f272021-03-24 23:04:19 -07002050 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002051 logger.Warn(ctx, err)
2052 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002053 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002054 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002055 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002056 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302057 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002058 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302059 "onu-id": onuID,
2060 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002061 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002062 "alloc-id": techprofileInst.AllocId,
2063 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002064 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002065 default:
2066 logger.Errorw(ctx, "error-unknown-tech",
2067 log.Fields{
2068 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002069 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302070 return nil
2071}
2072
David K. Bainbridge794735f2020-02-11 21:01:37 -08002073// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002074func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002075 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302076 log.Fields{
2077 "flowDirection": flowDirection,
2078 "flow": *flow,
2079 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002080
2081 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002082 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002083 }
2084
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302085 classifierInfo := make(map[string]interface{})
2086
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002087 portNum, Intf, onu, uni, inPort, ethType, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302088 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002089 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002090 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302091 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302092
David K. Bainbridge794735f2020-02-11 21:01:37 -08002093 onuID := int32(onu)
2094 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002095 tpID, err := getTpIDFromFlow(ctx, flow)
2096 if err != nil {
2097 return olterrors.NewErrNotFound("tp-id",
2098 log.Fields{
2099 "flow": flow,
2100 "intf-id": Intf,
2101 "onu-id": onuID,
2102 "uni-id": uniID,
2103 "device-id": f.deviceHandler.device.Id}, err)
2104 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302105
2106 for _, field := range flows.GetOfbFields(flow) {
2107 if field.Type == flows.IP_PROTO {
2108 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002109 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302110 }
2111 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002112 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302113 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002114 "flow-id": flow.Id,
2115 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302116 "onu-id": onuID,
2117 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302118
2119 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2120 onuID = -1
2121 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002122 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002123 Intf, err = plt.IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002124 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002125 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002126 log.Fields{
2127 "port-number": inPort,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002128 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002129 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002130 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302131 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002132
2133 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2134 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002135 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2136 return err
2137 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002138
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002139 // Delete the flow-id to gemport list entry from the map now the flow is deleted.
Gamze Abaka745ccb72021-11-18 11:29:58 +00002140 f.flowIDToGemsLock.Lock()
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002141 delete(f.flowIDToGems, flow.Id)
2142 f.flowIDToGemsLock.Unlock()
2143
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002144 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002145 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2146 "flow-id": flow.Id,
2147 "device-id": f.deviceHandler.device.Id,
2148 "onu-id": onuID,
2149 "intf": Intf,
2150 "err": err,
2151 })
2152 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302153 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002154
Girish Gowdra82c80982021-03-26 16:22:02 -07002155 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2156 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2157 return err
2158 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002159 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002160}
2161
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002162//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002163func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002164
Matteo Scandolof16389e2021-05-18 00:47:08 +00002165 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302166 var direction string
2167 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002168
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302169 for _, action := range flows.GetActions(flow) {
2170 if action.Type == flows.OUTPUT {
2171 if out := action.GetOutput(); out != nil {
2172 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002173 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302174 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002175 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002176 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002177 }
2178 }
2179 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002180
2181 if flows.HasGroup(flow) {
2182 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002183 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002184 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302185 direction = Upstream
2186 } else {
2187 direction = Downstream
2188 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302189
Girish Gowdracefae192020-03-19 18:14:10 -07002190 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002191 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002192
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002193 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002194}
2195
Esin Karamanae41e2b2019-12-17 18:13:13 +00002196//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2197func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002198 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002199 if ethType, ok := classifierInfo[EthType]; ok {
2200 if ethType.(uint32) == IPv4EthType {
2201 if ipProto, ok := classifierInfo[IPProto]; ok {
2202 if ipProto.(uint32) == IgmpProto {
2203 return true
2204 }
2205 }
2206 }
2207 }
2208 }
2209 return false
2210}
2211
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002212// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002213func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002214 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2215 // The device itself is going to be reset as part of deletion. So nothing to be done.
2216 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2217 return nil
2218 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002219 // Step1 : Fill flowControlBlock
2220 // Step2 : Push the flowControlBlock to ONU channel
2221 // Step3 : Wait on response channel for response
2222 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002223 startTime := time.Now()
2224 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002225 errChan := make(chan error)
2226 flowCb := flowControlBlock{
2227 ctx: ctx,
2228 addFlow: addFlow,
2229 flow: flow,
2230 flowMetadata: flowMetadata,
2231 errChan: &errChan,
2232 }
2233 inPort, outPort := getPorts(flow)
2234 var onuID uint32
2235 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002236 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002237 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002238 if f.flowHandlerRoutineActive[onuID] {
2239 // inPort or outPort is InvalidPort for trap-from-nni flows.
2240 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2241 // Send the flowCb on the ONU flow channel
2242 f.incomingFlows[onuID] <- flowCb
2243 // Wait on the channel for flow handlers return value
2244 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002245 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002246 return err
2247 }
2248 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2249 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002250}
2251
2252// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2253// 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 -07002254func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002255 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002256 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002257 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002258 // block on the channel to receive an incoming flow
2259 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002260 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002261 if flowCb.addFlow {
2262 logger.Info(flowCb.ctx, "adding-flow-start")
2263 startTime := time.Now()
2264 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2265 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2266 // Pass the return value over the return channel
2267 *flowCb.errChan <- err
2268 } else {
2269 logger.Info(flowCb.ctx, "removing-flow-start")
2270 startTime := time.Now()
2271 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2272 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2273 // Pass the return value over the return channel
2274 *flowCb.errChan <- err
2275 }
2276 case <-stopHandler:
2277 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2278 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002279 }
2280 }
2281}
2282
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002283// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002284func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002285 for i, v := range f.stopFlowHandlerRoutine {
2286 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002287 select {
2288 case v <- true:
2289 case <-time.After(time.Second * 5):
2290 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2291 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002292 }
2293 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002294 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002295 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2296}
2297
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002298// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302299// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002300func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002301 classifierInfo := make(map[string]interface{})
2302 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002303 var UsMeterID uint32
2304 var DsMeterID uint32
2305
Neha Sharma96b7bf22020-06-15 10:37:32 +00002306 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302307 log.Fields{
2308 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002309 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002310 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002311
Neha Sharma96b7bf22020-06-15 10:37:32 +00002312 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002313 if err != nil {
2314 // Error logging is already done in the called function
2315 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002316 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302317 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002318
Esin Karamanccb714b2019-11-29 15:02:06 +00002319 if flows.HasGroup(flow) {
2320 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002321 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002322 }
2323
manikkaraj k17652a72019-05-06 09:06:36 -04002324 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002325 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002326 if err != nil {
2327 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002328 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002329 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002330
Neha Sharma96b7bf22020-06-15 10:37:32 +00002331 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302332 log.Fields{
2333 "classifierinfo_inport": classifierInfo[InPort],
2334 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002335 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002336
Humera Kouser94d7a842019-08-25 19:04:32 -04002337 if ethType, ok := classifierInfo[EthType]; ok {
2338 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002339 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002340 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002341 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002342 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002343 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002344 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2345 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2346 }
2347 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002348 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002349 if ipProto, ok := classifierInfo[IPProto]; ok {
2350 if ipProto.(uint32) == IPProtoDhcp {
2351 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302352 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002353 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002354 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002355 }
2356 }
2357 }
2358 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002359 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002360 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002361 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002362 }
A R Karthick1f85b802019-10-11 05:06:05 +00002363
npujarec5762e2020-01-01 14:08:48 +05302364 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002365 // also update flowmgr cache
2366 f.onuGemInfoLock.Lock()
2367 onugem, ok := f.onuGemInfoMap[onuID]
2368 if ok {
2369 found := false
2370 for _, uni := range onugem.UniPorts {
2371 if uni == portNo {
2372 found = true
2373 break
2374 }
2375 }
2376 if !found {
2377 onugem.UniPorts = append(onugem.UniPorts, portNo)
2378 f.onuGemInfoMap[onuID] = onugem
2379 logger.Infow(ctx, "added uni port to onugem cache", log.Fields{"uni": portNo})
2380 }
2381 }
2382 f.onuGemInfoLock.Unlock()
A R Karthick1f85b802019-10-11 05:06:05 +00002383
Neha Sharma96b7bf22020-06-15 10:37:32 +00002384 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002385 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302386 return olterrors.NewErrNotFound("tpid-for-flow",
2387 log.Fields{
2388 "flow": flow,
2389 "intf-id": IntfID,
2390 "onu-id": onuID,
2391 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002392 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002393 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302394 log.Fields{
2395 "tp-id": TpID,
2396 "intf-id": intfID,
2397 "onu-id": onuID,
2398 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002399 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002400 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002401 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002402 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002403 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002404 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002405
2406 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002407 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002408}
Girish Gowdra3d633032019-12-10 16:37:05 +05302409
Esin Karamanccb714b2019-11-29 15:02:06 +00002410// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002411func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302412 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002413 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302414 "classifier-info": classifierInfo,
2415 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002416
Esin Karaman65409d82020-03-18 10:58:18 +00002417 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002418 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002419 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002420 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002421
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002422 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002423
David K. Bainbridge794735f2020-02-11 21:01:37 -08002424 onuID := NoneOnuID
2425 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002426
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002427 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002428 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002429 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002430 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002431 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2432 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002433 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002434 }
2435 groupID := actionInfo[GroupID].(uint32)
2436 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002437 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002438 FlowType: Multicast,
2439 NetworkIntfId: int32(networkInterfaceID),
2440 GroupId: groupID,
2441 Classifier: classifierProto,
2442 Priority: int32(flow.Priority),
2443 Cookie: flow.Cookie}
2444
Kent Hagermane6ff1012020-07-14 15:07:53 -04002445 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002446 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002447 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002448 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002449 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002450 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002451 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002452 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002453 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002454 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002455 //cached group can be removed now
2456 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002457 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002458 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002459 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002460
David K. Bainbridge794735f2020-02-11 21:01:37 -08002461 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002462}
2463
Esin Karaman65409d82020-03-18 10:58:18 +00002464//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2465func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2466 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002467 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002468 if err != nil {
2469 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2470 }
2471 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002472 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002473
2474 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2475 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002476}
2477
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002478//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002479func (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 -07002480
Neha Sharma96b7bf22020-06-15 10:37:32 +00002481 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302482 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002483 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302484 log.Fields{
2485 "intf-id": intfID,
2486 "onu-id": onuID,
2487 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002488 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302489 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002490 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002491
Neha Sharma96b7bf22020-06-15 10:37:32 +00002492 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002493 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002494 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002495 UniId: uniID,
2496 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002497 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002498 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002499 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002500
2501 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2502 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302503 return olterrors.NewErrCommunication("send-techprofile-download-request",
2504 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002505 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302506 "to-adapter": onuDev.deviceType,
2507 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002508 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002509 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002510 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302511 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302512}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002513
Girish Gowdra197acc12021-08-16 10:59:45 -07002514//AddOnuInfoToFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2515func (f *OpenOltFlowMgr) AddOnuInfoToFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302516
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002517 f.onuGemInfoLock.RLock()
2518 _, ok := f.onuGemInfoMap[onuID]
2519 f.onuGemInfoLock.RUnlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002520 // If the ONU already exists in onuGemInfo list, nothing to do
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002521 if ok {
2522 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2523 log.Fields{"onuID": onuID,
2524 "serialNum": serialNum})
2525 return nil
Girish Gowdra9602eb42020-09-09 15:50:39 -07002526 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002527
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002528 onuGemInfo := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2529 f.onuGemInfoLock.Lock()
2530 f.onuGemInfoMap[onuID] = &onuGemInfo
2531 f.onuGemInfoLock.Unlock()
2532 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onuID, onuGemInfo); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002533 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302534 }
Girish Gowdra197acc12021-08-16 10:59:45 -07002535 logger.Infow(ctx, "added-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302536 log.Fields{
2537 "intf-id": intfID,
2538 "onu-id": onuID,
2539 "serial-num": serialNum,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002540 "onu": onuGemInfo,
Shrey Baid26912972020-04-16 21:02:31 +05302541 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002542 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002543}
2544
Girish Gowdra197acc12021-08-16 10:59:45 -07002545//RemoveOnuInfoFromFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2546func (f *OpenOltFlowMgr) RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32) error {
2547
2548 f.onuGemInfoLock.Lock()
2549 delete(f.onuGemInfoMap, onuID)
2550 f.onuGemInfoLock.Unlock()
2551
2552 if err := f.resourceMgr.DelOnuGemInfo(ctx, intfID, onuID); err != nil {
2553 return err
2554 }
2555 logger.Infow(ctx, "deleted-onuinfo",
2556 log.Fields{
2557 "intf-id": intfID,
2558 "onu-id": onuID,
2559 "device-id": f.deviceHandler.device.Id})
2560 return nil
2561}
2562
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302563//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302564func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002565
Neha Sharma96b7bf22020-06-15 10:37:32 +00002566 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302567 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002568 "gem-port-id": gemPort,
2569 "intf-id": intfID,
2570 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002571 "device-id": f.deviceHandler.device.Id})
2572 f.onuGemInfoLock.RLock()
2573 onugem, ok := f.onuGemInfoMap[onuID]
2574 f.onuGemInfoLock.RUnlock()
2575 if !ok {
2576 logger.Warnw(ctx, "onu gem info is missing", log.Fields{
2577 "gem-port-id": gemPort,
2578 "intf-id": intfID,
2579 "onu-id": onuID,
2580 "device-id": f.deviceHandler.device.Id})
2581 return
2582 }
2583
2584 if onugem.OnuID == onuID {
2585 // check if gem already exists , else update the cache and kvstore
2586 for _, gem := range onugem.GemPorts {
2587 if gem == gemPort {
2588 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2589 log.Fields{
2590 "gem": gemPort,
2591 "device-id": f.deviceHandler.device.Id})
2592 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302593 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302594 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002595 onugem.GemPorts = append(onugem.GemPorts, gemPort)
2596 f.onuGemInfoLock.Lock()
2597 f.onuGemInfoMap[onuID] = onugem
2598 f.onuGemInfoLock.Unlock()
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002599 logger.Debugw(ctx, "updated onu gem info from cache", log.Fields{"onugem": onugem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002600 } else {
2601 logger.Warnw(ctx, "mismatched onu id", log.Fields{
2602 "gem-port-id": gemPort,
2603 "intf-id": intfID,
2604 "onu-id": onuID,
2605 "device-id": f.deviceHandler.device.Id})
2606 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302607 }
npujarec5762e2020-01-01 14:08:48 +05302608 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302609 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002610 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302611 log.Fields{
2612 "intf-id": intfID,
2613 "onu-id": onuID,
2614 "gemPort": gemPort,
2615 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002616 return
2617 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002618 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302619 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002620 "gem-port-id": gemPort,
2621 "intf-id": intfID,
2622 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002623 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002624}
2625
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002626//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302627func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002628 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002629
2630 if packetIn.IntfType == "pon" {
2631 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002632 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002633 onuID, uniID := packetIn.OnuId, packetIn.UniId
2634 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 +00002635
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002636 if packetIn.PortNo != 0 {
2637 logicalPortNum = packetIn.PortNo
2638 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002639 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002640 }
2641 // 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 +00002642 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002643 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002644 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002645 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002646
2647 if logger.V(log.DebugLevel) {
2648 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2649 log.Fields{
2650 "logical-port-num": logicalPortNum,
2651 "intf-type": packetIn.IntfType,
2652 "packet": hex.EncodeToString(packetIn.Pkt),
2653 })
2654 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002655 return logicalPortNum, nil
2656}
2657
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002658//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002659func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002660 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002661
2662 ctag, priority, err := getCTagFromPacket(ctx, packet)
2663 if err != nil {
2664 return 0, err
2665 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302666
Esin Karaman7fb80c22020-07-16 14:23:33 +00002667 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002668 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002669 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002670 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002671 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302672 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002673 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302674 log.Fields{
2675 "pktinkey": pktInkey,
2676 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002677
2678 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002679 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302680 //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 +00002681 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302682 if err == nil {
2683 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002684 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302685 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002686 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002687 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302688 log.Fields{
2689 "pktinkey": pktInkey,
2690 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302691 return gemPortID, nil
2692 }
2693 }
Shrey Baid26912972020-04-16 21:02:31 +05302694 return uint32(0), olterrors.NewErrNotFound("gem-port",
2695 log.Fields{
2696 "pktinkey": pktInkey,
2697 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002698
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002699}
2700
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002701func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2702 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002703 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002704 classifier[PacketTagType] = DoubleTag
2705 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002706 /* We manage flowId resource pool on per PON port basis.
2707 Since this situation is tricky, as a hack, we pass the NNI port
2708 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002709 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002710 on NNI port, use onu_id as -1 (invalid)
2711 ****************** CAVEAT *******************
2712 This logic works if the NNI Port Id falls within the same valid
2713 range of PON Port Ids. If this doesn't work for some OLT Vendor
2714 we need to have a re-look at this.
2715 *********************************************
2716 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002717 onuID := -1
2718 uniID := -1
2719 gemPortID := -1
2720 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002721 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302722 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302723 return olterrors.NewErrNotFound("nni-intreface-id",
2724 log.Fields{
2725 "classifier": classifier,
2726 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002727 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302728 }
2729
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002730 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002731 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002732 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002733 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002734
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002735 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2736 log.Fields{
2737 "classifier": classifier,
2738 "action": action,
2739 "flowId": logicalFlow.Id,
2740 "intf-id": networkInterfaceID})
2741
David K. Bainbridge794735f2020-02-11 21:01:37 -08002742 classifierProto, err := makeOpenOltClassifierField(classifier)
2743 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002744 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002745 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002746 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002747 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002748 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002749 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002750 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002751 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002752 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2753 OnuId: int32(onuID), // OnuId not required
2754 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002755 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002756 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002757 AllocId: int32(allocID), // AllocId not used
2758 NetworkIntfId: int32(networkInterfaceID),
2759 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002760 Classifier: classifierProto,
2761 Action: actionProto,
2762 Priority: int32(logicalFlow.Priority),
2763 Cookie: logicalFlow.Cookie,
2764 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002765 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002766 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002767 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002768 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002769 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002770}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002771
Esin Karamanae41e2b2019-12-17 18:13:13 +00002772//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2773func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2774 var packetType string
2775 ovid, ivid := false, false
2776 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2777 vid := vlanID & VlanvIDMask
2778 if vid != ReservedVlan {
2779 ovid = true
2780 }
2781 }
2782 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2783 vid := uint32(metadata)
2784 if vid != ReservedVlan {
2785 ivid = true
2786 }
2787 }
2788 if ovid && ivid {
2789 packetType = DoubleTag
2790 } else if !ovid && !ivid {
2791 packetType = Untagged
2792 } else {
2793 packetType = SingleTag
2794 }
2795 return packetType
2796}
2797
2798//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002799func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002800 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002801 action := make(map[string]interface{})
2802 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2803 action[TrapToHost] = true
2804 /* We manage flowId resource pool on per PON port basis.
2805 Since this situation is tricky, as a hack, we pass the NNI port
2806 index (network_intf_id) as PON port Index for the flowId resource
2807 pool. Also, there is no ONU Id available for trapping packets
2808 on NNI port, use onu_id as -1 (invalid)
2809 ****************** CAVEAT *******************
2810 This logic works if the NNI Port Id falls within the same valid
2811 range of PON Port Ids. If this doesn't work for some OLT Vendor
2812 we need to have a re-look at this.
2813 *********************************************
2814 */
2815 onuID := -1
2816 uniID := -1
2817 gemPortID := -1
2818 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002819 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002820 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302821 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002822 "classifier": classifier,
2823 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002824 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002825 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002826 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002827 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002828 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002829 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002830
David K. Bainbridge794735f2020-02-11 21:01:37 -08002831 classifierProto, err := makeOpenOltClassifierField(classifier)
2832 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002833 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002834 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002835 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002836 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002837 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002838 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002839 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002840 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002841 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2842 OnuId: int32(onuID), // OnuId not required
2843 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002844 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002845 FlowType: Downstream,
2846 AllocId: int32(allocID), // AllocId not used
2847 NetworkIntfId: int32(networkInterfaceID),
2848 GemportId: int32(gemPortID), // GemportId not used
2849 Classifier: classifierProto,
2850 Action: actionProto,
2851 Priority: int32(logicalFlow.Priority),
2852 Cookie: logicalFlow.Cookie,
2853 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002854 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002855 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002856 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002857 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002858
David K. Bainbridge794735f2020-02-11 21:01:37 -08002859 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002860}
2861
salmansiddiqui7ac62132019-08-22 03:58:50 +00002862func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2863 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302864 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002865 }
2866 if Dir == tp_pb.Direction_UPSTREAM {
2867 return "upstream", nil
2868 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2869 return "downstream", nil
2870 }
2871 return "", nil
2872}
2873
Kent Hagermane6ff1012020-07-14 15:07:53 -04002874// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302875func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002876 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002877 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002878 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002879 intfID := args[IntfID]
2880 onuID := args[OnuID]
2881 uniID := args[UniID]
2882 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002883 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002884 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002885 gemToAes := make(map[uint32]bool)
2886
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002887 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002888 var direction = tp_pb.Direction_UPSTREAM
2889 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002890 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002891 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002892 attributes = TpInst.UpstreamGemPortAttributeList
2893 } else {
2894 attributes = TpInst.DownstreamGemPortAttributeList
2895 direction = tp_pb.Direction_DOWNSTREAM
2896 }
2897 default:
2898 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002899 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002900 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002901
2902 if len(gemPorts) == 1 {
2903 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002904 gemPortID = gemPorts[0]
2905 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002906 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2907 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002908 pBitMap := attributes[idx].PbitMap
2909 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2910 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2911 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002912 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002913 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2914 if pbitSet == pbit1 {
2915 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2916 pbitToGem[pcp] = gemID
2917 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002918 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002919 }
2920 }
2921 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002922 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2923 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2924 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002925 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002926 }
2927
Gamze Abaka7650be62021-02-26 10:50:36 +00002928 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2929 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2930
salmansiddiqui7ac62132019-08-22 03:58:50 +00002931 if ipProto, ok := classifierInfo[IPProto]; ok {
2932 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002933 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002934 "tp-id": tpID,
2935 "alloc-id": allocID,
2936 "intf-id": intfID,
2937 "onu-id": onuID,
2938 "uni-id": uniID,
2939 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002940 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002941 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002942 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002943 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})
2944 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002945 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002946 }
2947
Girish Gowdra32625212020-04-29 11:26:35 -07002948 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002949 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302950 log.Fields{
2951 "intf-id": intfID,
2952 "onu-id": onuID,
2953 "uni-id": uniID,
2954 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002955 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002956 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002957 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})
2958 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002959 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002960 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002961 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002962 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002963 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002964 }
2965 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002966 if ethType.(uint32) == EapEthType {
2967 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002968 "intf-id": intfID,
2969 "onu-id": onuID,
2970 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002971 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002972 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002973 var vlanID uint32
2974 if val, ok := classifierInfo[VlanVid]; ok {
2975 vlanID = (val.(uint32)) & VlanvIDMask
2976 } else {
2977 vlanID = DefaultMgmtVlan
2978 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002979 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002980 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002981 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})
2982 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002983 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002984 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002985 } else if ethType.(uint32) == PPPoEDEthType {
2986 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2987 "tp-id": tpID,
2988 "alloc-id": allocID,
2989 "intf-id": intfID,
2990 "onu-id": onuID,
2991 "uni-id": uniID,
2992 })
2993 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002994 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002995 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002996 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})
2997 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002998 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002999 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003000 }
Gamze Abaka7650be62021-02-26 10:50:36 +00003001 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003002 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003003 "intf-id": intfID,
3004 "onu-id": onuID,
3005 "uni-id": uniID,
3006 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003007 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00003008 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003009 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003010 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})
3011 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003012 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00003013 }
Gamze Abaka7650be62021-02-26 10:50:36 +00003014 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003015 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003016 "intf-id": intfID,
3017 "onu-id": onuID,
3018 "uni-id": uniID,
3019 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003020 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00003021 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003022 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003023 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})
3024 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003025 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00003026 }
3027 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003028 return olterrors.NewErrInvalidValue(log.Fields{
3029 "intf-id": intfID,
3030 "onu-id": onuID,
3031 "uni-id": uniID,
3032 "classifier": classifierInfo,
3033 "action": actionInfo,
3034 "flow": flow},
3035 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003036 }
3037 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04003038 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003039 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003040 logger.Warn(ctx, err)
3041 }
3042 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003043 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00003044}
3045
Gamze Abaka745ccb72021-11-18 11:29:58 +00003046func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32, flowID uint64) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003047 f.gemToFlowIDsKey.RLock()
3048 flowIDList := f.gemToFlowIDs[gemPortID]
3049 f.gemToFlowIDsKey.RUnlock()
Gamze Abaka745ccb72021-11-18 11:29:58 +00003050 if len(flowIDList) > 0 {
3051 for _, id := range flowIDList {
3052 if flowID != id {
3053 return true
Gamze Abakafee36392019-10-03 11:17:24 +00003054 }
3055 }
3056 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00003057 return false
Gamze Abakacb0e6772021-06-10 08:32:12 +00003058}
Girish Gowdra54934262019-11-13 14:19:55 +05303059
Gamze Abakacb0e6772021-06-10 08:32:12 +00003060func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003061 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
3062 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
3063 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 +00003064 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303065 for i := 0; i < len(tpInstances); i++ {
3066 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00003067 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003068 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Gamze Abakacb0e6772021-06-10 08:32:12 +00003069 logger.Debugw(ctx, "alloc-is-in-use",
3070 log.Fields{
3071 "device-id": f.deviceHandler.device.Id,
3072 "intfID": sq.intfID,
3073 "onuID": sq.onuID,
3074 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003075 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00003076 })
3077 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303078 }
3079 }
3080 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003081 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003082}
3083
Neha Sharma96b7bf22020-06-15 10:37:32 +00003084func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003085 for _, field := range flows.GetOfbFields(flow) {
3086 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003087 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003088 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003089 } else if field.Type == flows.ETH_DST {
3090 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003091 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003092 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003093 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003094 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003095 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003096 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003097 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003098 } else if field.Type == flows.VLAN_VID {
Andrea Campanellafaa42152021-10-28 11:50:56 +05303099 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3100 if field.GetVlanVid() != ReservedVlan {
3101 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3102 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3103 }
Scott Baker355d1742019-10-24 10:57:52 -07003104 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003105 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003106 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003107 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003108 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003109 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003110 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003111 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003112 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003113 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003114 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003115 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003116 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003117 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003118 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003119 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003120 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003121 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003122 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003123 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003124 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003125 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003126 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003127 return
3128 }
3129 }
3130}
3131
Neha Sharma96b7bf22020-06-15 10:37:32 +00003132func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003133 for _, action := range flows.GetActions(flow) {
3134 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003135 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003136 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003137 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003138 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003139 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003140 }
Scott Baker355d1742019-10-24 10:57:52 -07003141 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003142 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003143 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003144 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003145 if out := action.GetPush(); out != nil {
3146 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003147 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003148 } else {
3149 actionInfo[PushVlan] = true
3150 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003151 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303152 log.Fields{
3153 "push-tpid": actionInfo[TPID].(uint32),
3154 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003155 }
3156 }
Scott Baker355d1742019-10-24 10:57:52 -07003157 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003158 if out := action.GetSetField(); out != nil {
3159 if field := out.GetField(); field != nil {
3160 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003161 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003162 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003163 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3164 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003165 }
3166 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003167 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003168 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003169 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003170 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003171 }
3172 }
3173 return nil
3174}
3175
Neha Sharma96b7bf22020-06-15 10:37:32 +00003176func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003177 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003178 fieldtype := ofbField.GetType()
3179 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003180 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3181 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003182 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003183 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003184 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003185 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003186 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3187 pcp := ofbField.GetVlanPcp()
3188 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003189 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003190 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003191 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003192 }
3193 }
3194}
3195
Neha Sharma96b7bf22020-06-15 10:37:32 +00003196func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003197 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003198 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003199 } else {
3200 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003201 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003202 }
3203}
3204
Neha Sharma96b7bf22020-06-15 10:37:32 +00003205func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003206 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003207 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003208 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003209 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003210 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003211 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003212 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303213 log.Fields{
3214 "newinport": classifierInfo[InPort].(uint32),
3215 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003216 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303217 return olterrors.NewErrNotFound("child-in-port",
3218 log.Fields{
3219 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3220 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003221 }
3222 }
3223 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003224 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003225 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003226 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003227 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003228 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003229 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303230 log.Fields{
3231 "newoutport": actionInfo[Output].(uint32),
3232 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003233 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303234 return olterrors.NewErrNotFound("out-port",
3235 log.Fields{
3236 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3237 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003238 }
3239 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003240 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003241 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003242 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003243 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303244 log.Fields{
3245 "newinport": actionInfo[Output].(uint32),
3246 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003247 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303248 return olterrors.NewErrNotFound("nni-port",
3249 log.Fields{
3250 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3251 "in-port": classifierInfo[InPort].(uint32),
3252 "out-port": actionInfo[Output].(uint32),
3253 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003254 }
3255 }
3256 }
3257 return nil
3258}
Gamze Abakafee36392019-10-03 11:17:24 +00003259
Neha Sharma96b7bf22020-06-15 10:37:32 +00003260func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003261 /* Metadata 8 bytes:
3262 Most Significant 2 Bytes = Inner VLAN
3263 Next 2 Bytes = Tech Profile ID(TPID)
3264 Least Significant 4 Bytes = Port ID
3265 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3266 subscriber related flows.
3267 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003268 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003269 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003270 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003271 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003272 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003273 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003274}
3275
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003276func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3277 for _, sliceElement := range slice {
3278 if sliceElement == item {
3279 return slice
3280 }
3281 }
3282 return append(slice, item)
3283}
3284
3285func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003286 for _, sliceElement := range slice {
3287 if sliceElement == item {
3288 return slice
3289 }
3290 }
3291 return append(slice, item)
3292}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303293
3294// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003295func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303296
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003297 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303298 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003299 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003300 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003301 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003302 log.Fields{
3303 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003304 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003305 return uint32(0), err
3306 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003307 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303308 return intfID, nil
3309 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003310 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003311 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003312 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003313 log.Fields{
3314 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003315 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003316 return uint32(0), err
3317 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003318 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303319 return intfID, nil
3320 }
3321 return uint32(0), nil
3322}
3323
3324// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003325func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3326 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3327 if err != nil {
3328 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3329 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3330 return
3331 }
3332 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003333
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003334 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003335 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003336 f.packetInGemPortLock.RUnlock()
3337
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303338 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003339 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003340 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 +05303341 log.Fields{
3342 "pktinkey": pktInkey,
3343 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003344 return
3345 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303346 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003347 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003348 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003349 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003350
npujarec5762e2020-01-01 14:08:48 +05303351 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003352 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 +05303353 log.Fields{
3354 "pktinkey": pktInkey,
3355 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303356}
3357
Esin Karaman7fb80c22020-07-16 14:23:33 +00003358//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3359func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3360 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003361 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003362 return 0, 0, errors.New("invalid packet length")
3363 }
3364 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3365 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3366
3367 var index int8
3368 if outerEthType == 0x8100 {
3369 if innerEthType == 0x8100 {
3370 // q-in-q 802.1ad or 802.1q double tagged packet.
3371 // get the inner vlanId
3372 index = 18
3373 } else {
3374 index = 14
3375 }
3376 priority := (packet[index] >> 5) & 0x7
3377 //13 bits composes vlanId value
3378 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3379 return vlan, priority, nil
3380 }
3381 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3382 return 0, 0, nil
3383}
3384
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003385func (f *OpenOltFlowMgr) loadFlowIDsForGemAndGemIDsForFlow(ctx context.Context) {
3386 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - start")
3387 f.onuGemInfoLock.RLock()
3388 f.gemToFlowIDsKey.Lock()
3389 f.flowIDToGemsLock.Lock()
3390 for _, og := range f.onuGemInfoMap {
3391 for _, gem := range og.GemPorts {
3392 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, f.ponPortIdx, gem)
Gamze Abaka6f345c12021-09-08 01:14:33 +00003393 if err == nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003394 f.gemToFlowIDs[gem] = flowIDs
3395 for _, flowID := range flowIDs {
3396 if _, ok := f.flowIDToGems[flowID]; !ok {
3397 f.flowIDToGems[flowID] = []uint32{gem}
3398 } else {
3399 f.flowIDToGems[flowID] = appendUnique32bit(f.flowIDToGems[flowID], gem)
3400 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303401 }
3402 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303403 }
3404 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003405 f.flowIDToGemsLock.Unlock()
3406 f.gemToFlowIDsKey.Unlock()
3407 f.onuGemInfoLock.RUnlock()
3408 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - end")
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303409}
Esin Karamanccb714b2019-11-29 15:02:06 +00003410
Girish Gowdra9602eb42020-09-09 15:50:39 -07003411//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3412// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003413func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003414 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003415 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3416 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003417 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003418 "flow-id": flow.Id,
3419 "device-id": f.deviceHandler.device.Id})
3420 // Remove from device
3421 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3422 // DKB
3423 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3424 log.Fields{
3425 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003426 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003427 return err
3428 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003429
3430 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003431}
3432
khenaidoodc2116e2021-10-19 17:33:19 -04003433func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003434 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003435 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003436 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003437 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003438 }
3439
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003440 switch tpInst := tpInst.(type) {
3441 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003442 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003443 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003444 DeviceId: onuDeviceID,
3445 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003446 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003447 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003448 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003449 case *tp_pb.EponTechProfileInstance:
3450 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003451 DeviceId: onuDeviceID,
3452 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003453 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003454 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003455 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003456 default:
3457 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003458 }
khenaidoodc2116e2021-10-19 17:33:19 -04003459 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003460 DeviceId: onuDeviceID,
3461 UniId: uniID,
3462 TpInstancePath: tpPath,
3463 TechTpInstance: nil,
3464 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003465}
3466
Girish Gowdrabcf98af2021-07-01 08:24:42 -07003467func (f *OpenOltFlowMgr) getOnuGemInfoList(ctx context.Context) []rsrcMgr.OnuGemInfo {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003468 var onuGemInfoLst []rsrcMgr.OnuGemInfo
3469 f.onuGemInfoLock.RLock()
3470 defer f.onuGemInfoLock.RUnlock()
3471 for _, v := range f.onuGemInfoMap {
3472 onuGemInfoLst = append(onuGemInfoLst, *v)
3473 }
3474 return onuGemInfoLst
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003475}
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003476
3477// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3478func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
3479
3480 intfID := sq.intfID
3481 onuID := sq.onuID
3482 uniID := sq.uniID
3483 tpID := sq.tpID
3484
3485 var reverseDirection string
3486 if sq.direction == tp_pb.Direction_UPSTREAM {
3487 reverseDirection = "downstream"
3488 } else {
3489 reverseDirection = "upstream"
3490 }
3491
3492 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
3493 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, intfID, onuID, uniID, tpID); KvStoreMeter != nil {
3494 return
3495 }
3496
3497 // revert-delete tech-profile instance and delete tech profile id for onu
3498 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})
3499 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3500 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
3501 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, onuID, uniID, tpID)
3502
3503 // free gem/alloc
3504 switch techprofileInst := sq.tpInst.(type) {
3505 case *tp_pb.TechProfileInstance:
3506 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
3507 f.resourceMgr.FreeGemPortID(ctx, intfID, onuID, uniID, gem.GemportId)
3508 }
3509 f.resourceMgr.FreeAllocID(ctx, intfID, onuID, uniID, techprofileInst.UsScheduler.AllocId)
3510 }
3511}
3512
3513// revertSchduler is called when CreateQueues request fails
3514func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3515 // revert scheduler
3516 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})
3517 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
3518 IntfId: sq.intfID, OnuId: sq.onuID,
3519 UniId: sq.uniID, PortNo: sq.uniPort,
3520 TrafficScheds: TrafficSched})
3521}