blob: b82d7f6e9bc4cc9d7935154d18fd676aec971165 [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"
22 "crypto/md5"
Matteo Scandolo6056e822019-11-13 14:05:29 -080023 "encoding/hex"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "encoding/json"
Girish Gowdracefae192020-03-19 18:14:10 -070025 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053026 "fmt"
Esin Karamanccb714b2019-11-29 15:02:06 +000027 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
28 "github.com/opencord/voltha-lib-go/v3/pkg/log"
29 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080030 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000031 "github.com/opencord/voltha-protos/v3/go/common"
32 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
33 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
34 openoltpb2 "github.com/opencord/voltha-protos/v3/go/openolt"
35 tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
36 "github.com/opencord/voltha-protos/v3/go/voltha"
Girish Gowdra9602eb42020-09-09 15:50:39 -070037 "math/big"
38 "strings"
39 "sync"
Chaitrashree G S579fe732019-08-20 20:50:47 -040040
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040041 //deepcopy "github.com/getlantern/deepcopy"
Girish Gowdra3d633032019-12-10 16:37:05 +053042 "github.com/EagleChen/mapmutex"
Thomas Lee S94109f12020-03-03 16:39:29 +053043 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000044 "google.golang.org/grpc/codes"
45 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053046)
47
48const (
49 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053050
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070051 //HsiaFlow flow category
52 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053053
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070054 //EapolFlow flow category
55 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053056
Manikkaraj kb1d51442019-07-23 10:41:02 -040057 //DhcpFlow flow category
58 DhcpFlow = "DHCP_FLOW"
59
Esin Karamanccb714b2019-11-29 15:02:06 +000060 //MulticastFlow flow category
61 MulticastFlow = "MULTICAST_FLOW"
62
Esin Karamanae41e2b2019-12-17 18:13:13 +000063 //IgmpFlow flow category
64 IgmpFlow = "IGMP_FLOW"
65
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070066 //IPProtoDhcp flow category
67 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053068
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070069 //IPProtoIgmp flow category
70 IPProtoIgmp = 2
71
72 //EapEthType eapethtype value
73 EapEthType = 0x888e
74 //LldpEthType lldp ethtype value
75 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000076 //IPv4EthType IPv4 ethernet type value
77 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070078
79 //IgmpProto proto value
80 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053081
Andrea Campanella7acc0b92020-02-14 09:20:49 +010082 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
83 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040084
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070085 //DefaultMgmtVlan default vlan value
86 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053087
manikkaraj kbf256be2019-03-25 00:13:48 +053088 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089
David K. Bainbridge82efc492019-09-04 09:57:11 -070090 //Upstream constant
91 Upstream = "upstream"
92 //Downstream constant
93 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000094 //Multicast constant
95 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070096 //PacketTagType constant
97 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070098 //Untagged constant
99 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700100 //SingleTag constant
101 SingleTag = "single_tag"
102 //DoubleTag constant
103 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +0530104
105 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700106
107 //EthType constant
108 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +0000109 //EthDst constant
110 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111 //TPID constant
112 TPID = "tpid"
113 //IPProto constant
114 IPProto = "ip_proto"
115 //InPort constant
116 InPort = "in_port"
117 //VlanVid constant
118 VlanVid = "vlan_vid"
119 //VlanPcp constant
120 VlanPcp = "vlan_pcp"
121
122 //UDPDst constant
123 UDPDst = "udp_dst"
124 //UDPSrc constant
125 UDPSrc = "udp_src"
126 //Ipv4Dst constant
127 Ipv4Dst = "ipv4_dst"
128 //Ipv4Src constant
129 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700130 //Metadata constant
131 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700132 //TunnelID constant
133 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700134 //Output constant
135 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000136 //GroupID constant
137 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700138 // Actions
139
140 //PopVlan constant
141 PopVlan = "pop_vlan"
142 //PushVlan constant
143 PushVlan = "push_vlan"
144 //TrapToHost constant
145 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400146 //MaxMeterBand constant
147 MaxMeterBand = 2
148 //VlanPCPMask contant
149 VlanPCPMask = 0xFF
150 //VlanvIDMask constant
151 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000152 //IntfID constant
153 IntfID = "intfId"
154 //OnuID constant
155 OnuID = "onuId"
156 //UniID constant
157 UniID = "uniId"
158 //PortNo constant
159 PortNo = "portNo"
160 //AllocID constant
161 AllocID = "allocId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000162
163 //NoneOnuID constant
164 NoneOnuID = -1
165 //NoneUniID constant
166 NoneUniID = -1
167 //NoneGemPortID constant
168 NoneGemPortID = -1
Girish Gowdrafae935c2020-02-17 19:21:44 +0530169
170 // BinaryStringPrefix is binary string prefix
171 BinaryStringPrefix = "0b"
172 // BinaryBit1 is binary bit 1 expressed as a character
173 BinaryBit1 = '1'
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700174
175 // MapMutex
176 maxRetry = 300
177 maxDelay = 100000000
178 baseDelay = 10000000
179 factor = 1.1
180 jitter = 0.2
manikkaraj kbf256be2019-03-25 00:13:48 +0530181)
182
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400183type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700184 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400185 gemPort uint32
186}
187
Girish Gowdra3d633032019-12-10 16:37:05 +0530188type tpLockKey struct {
189 intfID uint32
190 onuID uint32
191 uniID uint32
192}
193
Gamze Abakafee36392019-10-03 11:17:24 +0000194type schedQueue struct {
195 direction tp_pb.Direction
196 intfID uint32
197 onuID uint32
198 uniID uint32
199 tpID uint32
200 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700201 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000202 meterID uint32
203 flowMetadata *voltha.FlowMetadata
204}
205
Girish Gowdra9602eb42020-09-09 15:50:39 -0700206// pendingFlowRemoveDataKey is key to pendingFlowRemoveDataPerSubscriber map
207type pendingFlowRemoveDataKey struct {
208 intfID uint32
209 onuID uint32
210 uniID uint32
211}
212
213// pendingFlowRemoveData is value stored in pendingFlowRemoveDataPerSubscriber map
214// This holds the number of pending flow removes and also a signal channel to
215// to indicate the receiver when all flow removes are handled
216type pendingFlowRemoveData struct {
217 pendingFlowRemoveCount uint32
218 allFlowsRemoved chan struct{}
Esin Karamanccb714b2019-11-29 15:02:06 +0000219}
220
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700221//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530222type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000223 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000224 deviceHandler *DeviceHandler
Girish Gowdra9602eb42020-09-09 15:50:39 -0700225 grpMgr *OpenOltGroupMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000226 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000227 onuIdsLock sync.RWMutex
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700228 perGemPortLock *mapmutex.Mutex // lock to be used to access the flowsUsedByGemPort map
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530229 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
230 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700231 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700232 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache, indexed by IntfId
233 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700234 onuGemInfoLock sync.RWMutex
Girish Gowdra3d633032019-12-10 16:37:05 +0530235 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Girish Gowdra9602eb42020-09-09 15:50:39 -0700236 perUserFlowHandleLock *mapmutex.Mutex
237
238 // pendingFlowRemoveDataPerSubscriber map is used to maintain the context on a per
239 // subscriber basis for the number of pending flow removes. This data is used
240 // to process all the flow removes for a subscriber before handling flow adds.
241 // Interleaving flow delete and flow add processing has known to cause PON resource
242 // management contentions on a per subscriber bases, so we need ensure ordering.
243 pendingFlowRemoveDataPerSubscriber map[pendingFlowRemoveDataKey]pendingFlowRemoveData
244 pendingFlowRemoveDataPerSubscriberLock sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530245}
246
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700247//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdra9602eb42020-09-09 15:50:39 -0700248func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000249 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530250 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530251 var err error
252 var idx uint32
253
manikkaraj kbf256be2019-03-25 00:13:48 +0530254 flowMgr.deviceHandler = dh
Girish Gowdra9602eb42020-09-09 15:50:39 -0700255 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530256 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000257 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000258 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
259 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530260 return nil
261 }
William Kurkian740a09c2019-10-23 17:07:38 -0400262 flowMgr.onuIdsLock = sync.RWMutex{}
Girish Gowdra9602eb42020-09-09 15:50:39 -0700263 flowMgr.pendingFlowRemoveDataPerSubscriberLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530264 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
265 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530266 ponPorts := rMgr.DevInfo.GetPonPorts()
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700267 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo, ponPorts)
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700268 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700269 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(maxRetry, maxDelay, baseDelay, factor, jitter)
270 flowMgr.perGemPortLock = mapmutex.NewCustomizedMapMutex(maxRetry, maxDelay, baseDelay, factor, jitter)
Girish Gowdra9602eb42020-09-09 15:50:39 -0700271 flowMgr.pendingFlowRemoveDataPerSubscriber = make(map[pendingFlowRemoveDataKey]pendingFlowRemoveData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530272 //Load the onugem info cache from kv store on flowmanager start
273 for idx = 0; idx < ponPorts; idx++ {
npujarec5762e2020-01-01 14:08:48 +0530274 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000275 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530276 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530277 //Load flowID list per gem map per interface from the kvstore.
npujarec5762e2020-01-01 14:08:48 +0530278 flowMgr.loadFlowIDlistForGem(ctx, idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530279 }
Esin Karamanccb714b2019-11-29 15:02:06 +0000280 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700281 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000282 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530283 return &flowMgr
284}
285
Kent Hagermane6ff1012020-07-14 15:07:53 -0400286func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000287 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700288 if f.perGemPortLock.TryLock(gemPK) {
289 logger.Debugw(ctx, "registering-flow-for-device ",
290 log.Fields{
291 "flow": flowFromCore,
292 "device-id": f.deviceHandler.device.Id})
293 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
294 if !ok {
295 flowIDList = []uint32{deviceFlow.FlowId}
296 }
297 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
298 f.flowsUsedByGemPort[gemPK] = flowIDList
299
300 f.perGemPortLock.Unlock(gemPK)
301
302 // update the flowids for a gem to the KVstore
303 return f.resourceMgr.UpdateFlowIDsForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Gamze Abakafee36392019-10-03 11:17:24 +0000304 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700305 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
306 log.Fields{
307 "flow-from-core": flowFromCore,
308 "device-id": f.deviceHandler.device.Id,
309 "key": gemPK,
310 })
311 return olterrors.NewErrAdapter("failed-to-acquire-per-gem-port-lock", log.Fields{
312 "flow-from-core": flowFromCore,
313 "device-id": f.deviceHandler.device.Id,
314 "key": gemPK,
315 }, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400316}
317
Girish Gowdra9602eb42020-09-09 15:50:39 -0700318func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000319 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200320 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000321 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530322 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700323 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530324
Neha Sharma96b7bf22020-06-15 10:37:32 +0000325 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530326 "device-id": f.deviceHandler.device.Id,
327 "intf-id": intfID,
328 "onu-id": onuID,
329 "uni-id": uniID,
330 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700331 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530332 "action": actionInfo,
333 "usmeter-iD": UsMeterID,
334 "dsmeter-iD": DsMeterID,
335 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400336 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
337 // is because the flow is an NNI flow and there would be no onu resources associated with it
338 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400339 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200340 cause := "no-onu-id-for-flow"
341 fields := log.Fields{
342 "onu": onuID,
343 "port-no": portNo,
344 "classifer": classifierInfo,
345 "action": actionInfo,
346 "device-id": f.deviceHandler.device.Id}
347 logger.Errorw(ctx, cause, fields)
348 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530349 }
350
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700351 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000352 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530353 "uni": uni,
354 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530355
356 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
357 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000358 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530359 "device-id": f.deviceHandler.device.Id,
360 "intf-id": intfID,
361 "onu-id": onuID,
362 "uni-id": uniID,
363 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700364 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530365 "action": actionInfo,
366 "usmeter-id": UsMeterID,
367 "dsmeter-id": DsMeterID,
368 "tp-id": TpID})
npujarec5762e2020-01-01 14:08:48 +0530369 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530370 if allocID == 0 || gemPorts == nil || TpInst == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000371 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530372 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
Andrea Campanellabfe08432020-09-11 17:07:03 +0200373 return olterrors.NewErrNotFound(
374 "alloc-id-gem-ports-tp-unavailable",
375 nil, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +0530376 }
377 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 */
npujarec5762e2020-01-01 14:08:48 +0530387 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530388 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
389 } else {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200390 cause := "failed-to-acquire-per-user-flow-handle-lock"
391 fields := log.Fields{
392 "intf-id": intfID,
393 "onu-id": onuID,
394 "uni-id": uniID,
395 "flow-id": flow.Id,
396 "flow-cookie": flow.Cookie,
397 "device-id": f.deviceHandler.device.Id}
398 logger.Errorw(ctx, cause, fields)
399 return olterrors.NewErrAdapter(cause, fields, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400400 }
Andrea Campanellabfe08432020-09-11 17:07:03 +0200401 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530402}
403
salmansiddiqui7ac62132019-08-22 03:58:50 +0000404// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530405func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400406
Neha Sharma96b7bf22020-06-15 10:37:32 +0000407 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530408 log.Fields{"dir": sq.direction,
409 "intf-id": sq.intfID,
410 "onu-id": sq.onuID,
411 "uni-id": sq.uniID,
412 "tp-id": sq.tpID,
413 "meter-id": sq.meterID,
414 "tp-inst": sq.tpInst,
415 "flowmetadata": sq.flowMetadata,
416 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400417
Gamze Abakafee36392019-10-03 11:17:24 +0000418 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000419 if err != nil {
420 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400421 }
422
423 /* Lets make a simple assumption that if the meter-id is present on the KV store,
424 * then the scheduler and queues configuration is applied on the OLT device
425 * in the given direction.
426 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000427
Manikkaraj kb1d51442019-07-23 10:41:02 -0400428 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530429 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400430 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530431 return olterrors.NewErrNotFound("meter",
432 log.Fields{"intf-id": sq.intfID,
433 "onu-id": sq.onuID,
434 "uni-id": sq.uniID,
435 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400436 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000437
Manikkaraj kb1d51442019-07-23 10:41:02 -0400438 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000439 if KvStoreMeter.MeterId == sq.meterID {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000440 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400441 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400442 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530443 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800444 "unsupported": "meter-id",
445 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530446 "meter-id-in-flow": sq.meterID,
447 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400448 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000449
Neha Sharma96b7bf22020-06-15 10:37:32 +0000450 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530451 log.Fields{
452 "meter-id": sq.meterID,
453 "direction": Direction,
454 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000455
Gamze Abakafee36392019-10-03 11:17:24 +0000456 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000457 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000458 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000459 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400460 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000461
462 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530463 return olterrors.NewErrNotFound("scheduler-config",
464 log.Fields{
465 "intf-id": sq.intfID,
466 "direction": sq.direction,
467 "tp-inst": sq.tpInst,
468 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000469 }
470
Manikkaraj kb1d51442019-07-23 10:41:02 -0400471 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000472 if sq.flowMetadata != nil {
473 for _, meter := range sq.flowMetadata.Meters {
474 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400475 meterConfig = meter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000476 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Shrey Baid26912972020-04-16 21:02:31 +0530477 log.Fields{"meterConfig": meterConfig,
478 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400479 break
480 }
481 }
482 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000483 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400484 }
485 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530486 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800487 "reason": "Could-not-get-meterbands-from-flowMetadata",
488 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530489 "meter-id": sq.meterID,
490 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400491 } else if len(meterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000492 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Shrey Baid26912972020-04-16 21:02:31 +0530493 log.Fields{"Bands": meterConfig.Bands,
494 "meter-id": sq.meterID,
495 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530496 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800497 "reason": "Invalid-number-of-bands-in-meter",
498 "meterband-count": len(meterConfig.Bands),
499 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530500 "meter-id": sq.meterID,
501 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400502 }
503 cir := meterConfig.Bands[0].Rate
504 cbs := meterConfig.Bands[0].BurstSize
505 eir := meterConfig.Bands[1].Rate
506 ebs := meterConfig.Bands[1].BurstSize
507 pir := cir + eir
508 pbs := cbs + ebs
509 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
510
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700511 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000512 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400513
npujarec5762e2020-01-01 14:08:48 +0530514 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530515 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
516 log.Fields{"intf-id": sq.intfID,
517 "direction": sq.direction,
518 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400519 }
520
salmansiddiqui7ac62132019-08-22 03:58:50 +0000521 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400522 * store the meter id on the KV store, for further reference.
523 */
npujarec5762e2020-01-01 14:08:48 +0530524 if err := f.resourceMgr.UpdateMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530525 return olterrors.NewErrAdapter("failed-updating-meter-id",
526 log.Fields{"onu-id": sq.onuID,
527 "meter-id": sq.meterID,
528 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400529 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000530 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530531 log.Fields{"direction": Direction,
532 "Meter": meterConfig,
533 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400534 return nil
535}
536
npujarec5762e2020-01-01 14:08:48 +0530537func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000538 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000539
540 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530541 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
542 log.Fields{"intf-id": sq.intfID,
543 "direction": sq.direction,
544 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000545 }
546
Neha Sharma96b7bf22020-06-15 10:37:32 +0000547 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530548 log.Fields{
549 "direction": sq.direction,
550 "TrafficScheds": TrafficSched,
551 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530552 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000553 IntfId: sq.intfID, OnuId: sq.onuID,
554 UniId: sq.uniID, PortNo: sq.uniPort,
555 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000556 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000557 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000558 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530559 "direction": sq.direction,
560 "traffic-queues": trafficQueues,
561 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000562
563 // On receiving the CreateTrafficQueues request, the driver should create corresponding
564 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000565 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530566 log.Fields{"direction": sq.direction,
567 "traffic-queues": trafficQueues,
568 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530569 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000570 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
571 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000572 TrafficQueues: trafficQueues,
573 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530574 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000575 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000576 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530577 "direction": sq.direction,
578 "traffic-queues": trafficQueues,
579 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000580
Esin Karamanccb714b2019-11-29 15:02:06 +0000581 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000582 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000583 if len(multicastTrafficQueues) > 0 {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700584 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present {
Esin Karamanccb714b2019-11-29 15:02:06 +0000585 //assumed that there is only one queue per PON for the multicast service
586 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
587 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000588 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000589 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700590 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000591 gemPortID: multicastQueuePerPonPort.GemportId,
592 servicePriority: multicastQueuePerPonPort.Priority,
593 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700594 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000595 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400596 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
597 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
598 return err
599 }
Shrey Baid26912972020-04-16 21:02:31 +0530600
Neha Sharma96b7bf22020-06-15 10:37:32 +0000601 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000602 }
603 }
604 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000605 return nil
606}
607
salmansiddiqui7ac62132019-08-22 03:58:50 +0000608// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530609func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400610
611 var Direction string
612 var SchedCfg *tp_pb.SchedulerConfig
613 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000614 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530615 log.Fields{
616 "direction": sq.direction,
617 "intf-id": sq.intfID,
618 "onu-id": sq.onuID,
619 "uni-id": sq.uniID,
620 "uni-port": sq.uniPort,
621 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000622 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000623 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400624 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000625 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000626 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400627 Direction = "downstream"
628 }
629
Girish Kumar8f73fe02019-12-09 13:19:37 +0000630 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530631 return olterrors.NewErrNotFound("scheduler-config",
632 log.Fields{
633 "int-id": sq.intfID,
634 "direction": sq.direction,
635 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000636 }
637
npujarec5762e2020-01-01 14:08:48 +0530638 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400639 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530640 return olterrors.NewErrNotFound("meter",
641 log.Fields{
642 "onu-id": sq.onuID,
643 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400644 }
645 if KVStoreMeter == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000646 logger.Warnw(ctx, "no-meter-installed-yet",
Shrey Baid26912972020-04-16 21:02:31 +0530647 log.Fields{
648 "direction": Direction,
649 "intf-id": sq.intfID,
650 "onu-id": sq.onuID,
651 "uni-id": sq.uniID,
652 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400653 return nil
654 }
655 cir := KVStoreMeter.Bands[0].Rate
656 cbs := KVStoreMeter.Bands[0].BurstSize
657 eir := KVStoreMeter.Bands[1].Rate
658 ebs := KVStoreMeter.Bands[1].BurstSize
659 pir := cir + eir
660 pbs := cbs + ebs
661
662 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
663
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700664 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000665 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000666
Neha Sharma96b7bf22020-06-15 10:37:32 +0000667 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000668 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530669 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
670 log.Fields{
671 "intf-id": sq.intfID,
672 "direction": sq.direction,
673 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000674 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400675
npujarec5762e2020-01-01 14:08:48 +0530676 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000677 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
678 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000679 TrafficQueues: TrafficQueues,
680 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000681 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530682 log.Fields{
683 "intf-id": sq.intfID,
684 "traffic-queues": TrafficQueues,
685 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400686 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000687 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530688 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000689 IntfId: sq.intfID, OnuId: sq.onuID,
690 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400691 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000692 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530693 log.Fields{
694 "intf-id": sq.intfID,
695 "traffic-schedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400696 }
697
Neha Sharma96b7bf22020-06-15 10:37:32 +0000698 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000699
700 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400701 * delete the meter id on the KV store.
702 */
npujarec5762e2020-01-01 14:08:48 +0530703 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400704 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530705 return olterrors.NewErrAdapter("unable-to-remove-meter",
706 log.Fields{
707 "onu": sq.onuID,
708 "meter": KVStoreMeter.MeterId,
709 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400710 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000711 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530712 log.Fields{
713 "meter-id": KVStoreMeter.MeterId,
714 "dir": Direction,
715 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400716 return err
717}
718
Gamze Abakafee36392019-10-03 11:17:24 +0000719// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700720func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) (uint32, []uint32, interface{}) {
Gamze Abakafee36392019-10-03 11:17:24 +0000721 var allocIDs []uint32
722 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530723 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530724 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000725 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000726
npujarec5762e2020-01-01 14:08:48 +0530727 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
728 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400729
Neha Sharma96b7bf22020-06-15 10:37:32 +0000730 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530731
Neha Sharma96b7bf22020-06-15 10:37:32 +0000732 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530733 "intf-id": intfID,
734 "onu-id": onuID,
735 "uni-id": uniID,
736 "device-id": f.deviceHandler.device.Id,
737 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530738
Manikkaraj kb1d51442019-07-23 10:41:02 -0400739 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530740 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000741 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000742 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530743 log.Fields{
744 "path": tpPath,
745 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530746 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000747 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530748 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000749 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530750 log.Fields{
751 "error": err,
752 "tp-id": TpID,
753 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000754 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530755 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400756 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
757 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
758 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530759 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000760 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530761 log.Fields{
762 "uni": uni,
763 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530764 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530765 }
Gamze Abakafee36392019-10-03 11:17:24 +0000766
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700767 switch tpInst := techProfileInstance.(type) {
768 case *tp.TechProfile:
769 if UsMeterID != 0 {
770 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
771 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
772 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000773 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700774 log.Fields{
775 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700776 "onu-id": onuID,
777 "uni-id": uniID,
778 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700779 "meter-id": UsMeterID,
780 "device-id": f.deviceHandler.device.Id})
781 return 0, nil, nil
782 }
783 }
784 if DsMeterID != 0 {
785 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
786 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
787 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000788 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700789 log.Fields{
790 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700791 "onu-id": onuID,
792 "uni-id": uniID,
793 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700794 "meter-id": DsMeterID,
795 "device-id": f.deviceHandler.device.Id})
796 return 0, nil, nil
797 }
798 }
799 allocID := tpInst.UsScheduler.AllocID
800 for _, gem := range tpInst.UpstreamGemPortAttributeList {
801 gemPortIDs = append(gemPortIDs, gem.GemportID)
802 }
803 allocIDs = appendUnique(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000804
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700805 if tpInstanceExists {
806 return allocID, gemPortIDs, techProfileInstance
807 }
808
809 for _, gemPortID := range gemPortIDs {
810 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
811 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000812 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700813 log.Fields{
814 "alloc-ids": allocIDs,
815 "gemports": allgemPortIDs,
816 "device-id": f.deviceHandler.device.Id})
817 // Send Tconts and GEM ports to KV store
818 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530819 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700820 case *tp.EponProfile:
821 // CreateSchedulerQueues for EPON needs to be implemented here
822 // when voltha-protos for EPON is completed.
823 allocID := tpInst.AllocID
824 for _, gem := range tpInst.UpstreamQueueAttributeList {
825 gemPortIDs = append(gemPortIDs, gem.GemportID)
826 }
827 allocIDs = appendUnique(allocIDs, allocID)
828
829 if tpInstanceExists {
830 return allocID, gemPortIDs, techProfileInstance
831 }
832
833 for _, gemPortID := range gemPortIDs {
834 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
835 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000836 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700837 log.Fields{
838 "alloc-ids": allocIDs,
839 "gemports": allgemPortIDs,
840 "device-id": f.deviceHandler.device.Id})
841 // Send Tconts and GEM ports to KV store
842 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
843 return allocID, gemPortIDs, techProfileInstance
844 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000845 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700846 log.Fields{
847 "tpInst": tpInst})
848 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530849 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530850}
851
npujarec5762e2020-01-01 14:08:48 +0530852func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530853
Neha Sharma96b7bf22020-06-15 10:37:32 +0000854 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530855 log.Fields{
856 "intf-id": intfID,
857 "onu-id": onuID,
858 "uni-id": uniID,
859 "alloc-id": allocID,
860 "gemport-ids": gemPortIDs,
861 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530862 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530863 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000864 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 +0530865 }
npujarec5762e2020-01-01 14:08:48 +0530866 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000867 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 +0530868 }
npujarec5762e2020-01-01 14:08:48 +0530869 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000870 logger.Error(ctx, "error-while-uploading-gemtopon-map-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530871 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000872 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 -0400873 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530874 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400875 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530876}
877
Neha Sharma96b7bf22020-06-15 10:37:32 +0000878func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000879 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530880 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000881 for _, intfID := range techRange.IntfIds {
882 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400883 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000884 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530885 log.Fields{
886 "intf-id": intfID,
887 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530888 }
889 }
890 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400891 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530892 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530893 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800894 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530895 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
896 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530897 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000898 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530899 log.Fields{
900 "numofTech": tpCount,
901 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
902 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530903 return nil
904}
905
npujarec5762e2020-01-01 14:08:48 +0530906func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530907 portNo uint32, uplinkClassifier map[string]interface{},
908 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000909 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700910 uplinkClassifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000911 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530912 log.Fields{
913 "uplinkClassifier": uplinkClassifier,
914 "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800915 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000916 Upstream, logicalFlow, allocID, gemportID, tpID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530917 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530918}
919
npujarec5762e2020-01-01 14:08:48 +0530920func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530921 portNo uint32, downlinkClassifier map[string]interface{},
922 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000923 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700924 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000925 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530926 log.Fields{
927 "downlinkClassifier": downlinkClassifier,
928 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400929 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
930 if vlan, exists := downlinkClassifier[VlanVid]; exists {
931 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700932 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Neha Sharma96b7bf22020-06-15 10:37:32 +0000933 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, intfID, onuID, uniID) {
934 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530935 log.Fields{
936 "flow": logicalFlow,
937 "device-id": f.deviceHandler.device.Id,
938 "onu-id": onuID,
939 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800940 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400941 }
942 }
943 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530944 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400945
Manikkaraj k884c1242019-04-11 16:26:42 +0530946 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700947 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400948 // vlan_vid is a uint32. must be type asserted as such or conversion fails
949 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530950 if ok {
951 downlinkAction[VlanVid] = dlClVid & 0xfff
952 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530953 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530954 "reason": "failed-to-convert-vlanid-classifier",
955 "vlan-id": VlanVid,
956 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530957 }
958
David K. Bainbridge794735f2020-02-11 21:01:37 -0800959 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000960 Downstream, logicalFlow, allocID, gemportID, tpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530961}
962
npujarec5762e2020-01-01 14:08:48 +0530963func (f *OpenOltFlowMgr) addHSIAFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530964 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000965 allocID uint32, gemPortID uint32, tpID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530966 /* One of the OLT platform (Broadcom BAL) requires that symmetric
967 flows require the same flow_id to be used across UL and DL.
968 Since HSIA flow is the only symmetric flow currently, we need to
969 re-use the flow_id across both direction. The 'flow_category'
970 takes priority over flow_cookie to find any available HSIA_FLOW
971 id for the ONU.
972 */
Neha Sharma96b7bf22020-06-15 10:37:32 +0000973 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530974 log.Fields{
975 "intf-id": intfID,
976 "onu-id": onuID,
977 "uni-id": uniID,
978 "device-id": f.deviceHandler.device.Id,
979 "classifier": classifier,
980 "action": action,
981 "direction": direction,
982 "alloc-id": allocID,
983 "gemport-id": gemPortID,
984 "logicalflow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530985 var vlanPbit uint32 = 0xff // means no pbit
Gamze Abaka724d0852020-03-18 12:10:24 +0000986 var vlanVid uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400987 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000988 vlanPbit = classifier[VlanPcp].(uint32)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000989 logger.Debugw(ctx, "found-pbit-in-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530990 log.Fields{
991 "vlan-pbit": vlanPbit,
992 "intf-id": intfID,
993 "onu-id": onuID,
994 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800995 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000996 logger.Debugw(ctx, "pbit-not-found-in-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530997 log.Fields{
998 "vlan-pcp": VlanPcp,
999 "intf-id": intfID,
1000 "onu-id": onuID,
1001 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001002 }
Gamze Abaka724d0852020-03-18 12:10:24 +00001003 if _, ok := classifier[VlanVid]; ok {
1004 vlanVid = classifier[VlanVid].(uint32)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001005 logger.Debugw(ctx, "found-vlan-in-the-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301006 log.Fields{
1007 "vlan-vid": vlanVid,
1008 "intf-id": intfID,
1009 "onu-id": onuID,
1010 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001011 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001012 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301013 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001014 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301015 log.Fields{
1016 "device-id": f.deviceHandler.device.Id,
1017 "intf-id": intfID,
1018 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001019 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301020 }
Gamze Abaka724d0852020-03-18 12:10:24 +00001021 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +05301022 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301023 return olterrors.NewErrNotFound("hsia-flow-id",
1024 log.Fields{
1025 "direction": direction,
1026 "device-id": f.deviceHandler.device.Id,
1027 "intf-id": intfID,
1028 "onu-id": onuID,
1029 }, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301030 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001031 classifierProto, err := makeOpenOltClassifierField(classifier)
1032 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301033 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301034 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001035 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301036 log.Fields{
1037 "classifier": *classifierProto,
1038 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001039 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001040 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301041 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301042 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001043 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301044 log.Fields{
1045 "action": *actionProto,
1046 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001047 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301048 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301049 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001050 log.Fields{
1051 "classifier": classifier,
1052 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301053 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001054 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301055 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001056 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
1057 OnuId: int32(onuID),
1058 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +00001059 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +05301060 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001061 AllocId: int32(allocID),
1062 NetworkIntfId: int32(networkIntfID),
1063 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +05301064 Classifier: classifierProto,
1065 Action: actionProto,
1066 Priority: int32(logicalFlow.Priority),
1067 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001068 PortNo: portNo,
1069 TechProfileId: tpID,
1070 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001071 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301072 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301073 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001074 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301075 log.Fields{"direction": direction,
1076 "device-id": f.deviceHandler.device.Id,
1077 "flow": flow,
1078 "intf-id": intfID,
1079 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001080 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
1081 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1082 flow.OnuId,
1083 flow.UniId,
1084 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301085 return olterrors.NewErrPersistence("update", "flow", flowID,
1086 log.Fields{
1087 "flow": flow,
1088 "device-id": f.deviceHandler.device.Id,
1089 "intf-id": intfID,
1090 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001091 }
1092 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301093}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001094
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001095func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1096 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1097 gemPortID uint32, tpID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301098
Neha Sharma96b7bf22020-06-15 10:37:32 +00001099 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301100 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301101 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001102 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301103 "action": action,
1104 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001105 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301106 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301107
1108 // Clear the action map
1109 for k := range action {
1110 delete(action, k)
1111 }
1112
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001113 action[TrapToHost] = true
1114 classifier[UDPSrc] = uint32(68)
1115 classifier[UDPDst] = uint32(67)
1116 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301117
Neha Sharma96b7bf22020-06-15 10:37:32 +00001118 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301119 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001120 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301121 log.Fields{
1122 "device-id": f.deviceHandler.device.Id,
1123 "intf-id": intfID,
1124 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001125 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301126 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301127
David K. Bainbridge794735f2020-02-11 21:01:37 -08001128 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, DhcpFlow, 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301129
1130 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301131 return olterrors.NewErrNotFound("flow",
1132 log.Fields{
1133 "interface-id": intfID,
1134 "gem-port": gemPortID,
1135 "cookie": flowStoreCookie,
1136 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001137 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301138 }
1139
Neha Sharma96b7bf22020-06-15 10:37:32 +00001140 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301141 log.Fields{
1142 "ul_classifier": classifier,
1143 "ul_action": action,
1144 "uplinkFlowId": flowID,
1145 "intf-id": intfID,
1146 "onu-id": onuID,
1147 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301148
David K. Bainbridge794735f2020-02-11 21:01:37 -08001149 classifierProto, err := makeOpenOltClassifierField(classifier)
1150 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301151 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301152 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001153 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001154 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001155 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301156 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301157 }
1158
David K. Bainbridge794735f2020-02-11 21:01:37 -08001159 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001160 OnuId: int32(onuID),
1161 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301162 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001163 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001164 AllocId: int32(allocID),
1165 NetworkIntfId: int32(networkIntfID),
1166 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301167 Classifier: classifierProto,
1168 Action: actionProto,
1169 Priority: int32(logicalFlow.Priority),
1170 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001171 PortNo: portNo,
1172 TechProfileId: tpID,
1173 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001174 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301175 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001176 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001177 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301178 log.Fields{
1179 "device-id": f.deviceHandler.device.Id,
1180 "flow-id": flowID,
1181 "intf-id": intfID,
1182 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001183 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
1184 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
1185 dhcpFlow.OnuId,
1186 dhcpFlow.UniId,
1187 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301188 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1189 log.Fields{
1190 "flow": dhcpFlow,
1191 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301192 }
1193
David K. Bainbridge794735f2020-02-11 21:01:37 -08001194 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301195}
1196
Esin Karamanae41e2b2019-12-17 18:13:13 +00001197//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301198func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001199 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32) error {
1200 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001201}
1202
1203//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301204func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001205 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string, tpID uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001206
Neha Sharma96b7bf22020-06-15 10:37:32 +00001207 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001208 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301209 return olterrors.NewErrNotFound("nni-interface-id",
1210 log.Fields{
1211 "classifier": classifier,
1212 "action": action,
1213 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001214 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001215 }
1216
1217 // Clear the action map
1218 for k := range action {
1219 delete(action, k)
1220 }
1221
1222 action[TrapToHost] = true
1223 classifier[PacketTagType] = SingleTag
1224 delete(classifier, VlanVid)
1225
Neha Sharma96b7bf22020-06-15 10:37:32 +00001226 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301227 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001228 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001229 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001230 }
1231
npujarec5762e2020-01-01 14:08:48 +05301232 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, flowType, 0, 0 /*classifier[VLAN_PCP].(uint32)*/)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001233
1234 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301235 return olterrors.NewErrNotFound("flow-id",
1236 log.Fields{
1237 "intf-id": intfID,
1238 "oni-id": onuID,
1239 "cookie": flowStoreCookie,
1240 "flow-type": flowType,
1241 "device-id": f.deviceHandler.device.Id,
1242 "onu-id": onuID},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001243 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001244 }
1245
Neha Sharma96b7bf22020-06-15 10:37:32 +00001246 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301247 log.Fields{
1248 "ul_classifier": classifier,
1249 "ul_action": action,
1250 "uplinkFlowId": flowID,
1251 "flowType": flowType,
1252 "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),
1272 FlowId: flowID,
1273 FlowType: Upstream,
1274 AllocId: int32(allocID),
1275 NetworkIntfId: int32(networkIntfID),
1276 GemportId: int32(gemPortID),
1277 Classifier: classifierProto,
1278 Action: actionProto,
1279 Priority: int32(logicalFlow.Priority),
1280 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001281 PortNo: portNo,
1282 TechProfileId: tpID,
1283 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001284
David K. Bainbridge794735f2020-02-11 21:01:37 -08001285 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301286 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001287 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001288 logger.Infof(ctx, "%s ul-flow-added-to-device-successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001289
David K. Bainbridge794735f2020-02-11 21:01:37 -08001290 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
1291 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1292 flow.OnuId,
1293 flow.UniId,
1294 flow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301295 return olterrors.NewErrPersistence("update", "flow", flow.FlowId, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001296 }
1297
David K. Bainbridge794735f2020-02-11 21:01:37 -08001298 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001299}
1300
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001301// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001302func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1303 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1304 gemPortID uint32, vlanID uint32, tpID uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001305 logger.Infow(ctx, "adding-eapol-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301306 log.Fields{
1307 "intf-id": intfID,
1308 "onu-id": onuID,
1309 "port-no": portNo,
1310 "alloc-id": allocID,
1311 "gemport-id": gemPortID,
1312 "vlan-id": vlanID,
1313 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301314
1315 uplinkClassifier := make(map[string]interface{})
1316 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301317
manikkaraj kbf256be2019-03-25 00:13:48 +05301318 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001319 uplinkClassifier[EthType] = uint32(EapEthType)
1320 uplinkClassifier[PacketTagType] = SingleTag
1321 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001322 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301323 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001324 uplinkAction[TrapToHost] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00001325 flowStoreCookie := getFlowStoreCookie(ctx, uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301326 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001327 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301328 "device-id": f.deviceHandler.device.Id,
1329 "onu-id": onuID,
1330 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001331 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301332 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301333 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +00001334 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +05301335 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301336 return olterrors.NewErrNotFound("flow-id",
1337 log.Fields{
1338 "intf-id": intfID,
1339 "onu-id": onuID,
1340 "coookie": flowStoreCookie,
1341 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001342 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301343 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001344 logger.Debugw(ctx, "creating-ul-eapol-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301345 log.Fields{
1346 "ul_classifier": uplinkClassifier,
1347 "ul_action": uplinkAction,
1348 "uplinkFlowId": uplinkFlowID,
1349 "device-id": f.deviceHandler.device.Id,
1350 "intf-id": intfID,
1351 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301352
David K. Bainbridge794735f2020-02-11 21:01:37 -08001353 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1354 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301355 return olterrors.NewErrInvalidValue(log.Fields{
1356 "classifier": uplinkClassifier,
1357 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301358 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001359 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301360 log.Fields{
1361 "classifier": *classifierProto,
1362 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001363 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001364 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301365 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301366 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001367 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301368 log.Fields{
1369 "action": *actionProto,
1370 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001371 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301372 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301373 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001374 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301375 "action": action,
1376 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001377 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301378 }
1379
David K. Bainbridge794735f2020-02-11 21:01:37 -08001380 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001381 OnuId: int32(onuID),
1382 UniId: int32(uniID),
1383 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001384 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001385 AllocId: int32(allocID),
1386 NetworkIntfId: int32(networkIntfID),
1387 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301388 Classifier: classifierProto,
1389 Action: actionProto,
1390 Priority: int32(logicalFlow.Priority),
1391 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001392 PortNo: portNo,
1393 TechProfileId: tpID,
1394 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001395 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301396 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001397 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001398 logger.Infow(ctx, "eapol-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301399 log.Fields{
1400 "device-id": f.deviceHandler.device.Id,
1401 "onu-id": onuID,
1402 "intf-id": intfID,
1403 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001404 flowCategory := "EAPOL"
1405 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1406 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1407 upstreamFlow.OnuId,
1408 upstreamFlow.UniId,
1409 upstreamFlow.FlowId,
1410 /* lowCategory, */
1411 flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301412 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1413 log.Fields{
1414 "flow": upstreamFlow,
1415 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301416 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001417 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301418}
1419
David K. Bainbridge794735f2020-02-11 21:01:37 -08001420func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001421 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001422
1423 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1424 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1425 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001426 if vlanID != ReservedVlan {
1427 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001428 classifier.OVid = vid
1429 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301430 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001431 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1432 vid := uint32(metadata)
1433 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001434 classifier.IVid = vid
1435 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301436 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301437 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001438 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301439 classifier.OPbits = vlanPcp
1440 } else {
1441 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301442 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001443 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1444 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1445 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1446 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001447 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001448 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1449 classifier.PktTagType = pktTagType
1450
1451 switch pktTagType {
1452 case SingleTag:
1453 case DoubleTag:
1454 case Untagged:
1455 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001456 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301457 }
1458 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001459 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301460}
1461
Gamze Abaka724d0852020-03-18 12:10:24 +00001462func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001463 var actionCmd openoltpb2.ActionCmd
1464 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301465 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001466 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301467 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001468 if _, ok := actionInfo[VlanPcp]; ok {
1469 action.Cmd.RemarkInnerPbits = true
1470 action.IPbits = actionInfo[VlanPcp].(uint32)
1471 if _, ok := actionInfo[VlanVid]; ok {
1472 action.Cmd.TranslateInnerTag = true
1473 action.IVid = actionInfo[VlanVid].(uint32)
1474 }
1475 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001476 } else if _, ok := actionInfo[PushVlan]; ok {
1477 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301478 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001479 if _, ok := actionInfo[VlanPcp]; ok {
1480 action.OPbits = actionInfo[VlanPcp].(uint32)
1481 action.Cmd.RemarkOuterPbits = true
1482 if _, ok := classifierInfo[VlanVid]; ok {
1483 action.IVid = classifierInfo[VlanVid].(uint32)
1484 action.Cmd.TranslateInnerTag = true
1485 }
1486 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001487 } else if _, ok := actionInfo[TrapToHost]; ok {
1488 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301489 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001490 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301491 }
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 {
1497 return f.techprofile[intfID].GetTechProfileInstanceKVPath(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
npujarec5762e2020-01-01 14:08:48 +05301501func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1502 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001503 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1504
Gamze Abakafee36392019-10-03 11:17:24 +00001505 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301506 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001507 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301508 // return err
1509 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001510 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001511 logger.Debugw(ctx, "tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001512 }
1513 return nil
1514}
1515
1516// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301517func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001518 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001519 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001520 }
npujarec5762e2020-01-01 14:08:48 +05301521 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301522 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1523 log.Fields{
1524 "tp-id": tpID,
1525 "uni-port-name": uniPortName,
1526 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001527 }
1528 return nil
1529}
1530
Neha Sharma96b7bf22020-06-15 10:37:32 +00001531func getFlowStoreCookie(ctx context.Context, classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301532 if len(classifier) == 0 { // should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00001533 logger.Error(ctx, "invalid-classfier-object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301534 return 0
1535 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001536 logger.Debugw(ctx, "generating-flow-store-cookie",
Shrey Baid26912972020-04-16 21:02:31 +05301537 log.Fields{
1538 "classifier": classifier,
1539 "gemport-id": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301540 var jsonData []byte
1541 var flowString string
1542 var err error
1543 // TODO: Do we need to marshall ??
1544 if jsonData, err = json.Marshal(classifier); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001545 logger.Error(ctx, "failed-to-encode-classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301546 return 0
1547 }
1548 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001549 if gemPortID != 0 {
1550 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301551 }
1552 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001553 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301554 hash := big.NewInt(0)
1555 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301556 generatedHash := hash.Uint64()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001557 logger.Debugw(ctx, "hash-generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301558 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301559}
1560
npujarec5762e2020-01-01 14:08:48 +05301561func (f *OpenOltFlowMgr) getUpdatedFlowInfo(ctx context.Context, flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32, logicalFlowID uint64) *[]rsrcMgr.FlowInfo {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301562 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001563 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001564 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1565 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1566 */
1567 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001568 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001569 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001570 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001571 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001572 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301573 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001574 if existingFlows != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001575 logger.Debugw(ctx, "flow-exists-for-given-flowID--appending-it-to-current-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301576 log.Fields{
1577 "flow-id": flow.FlowId,
1578 "device-id": f.deviceHandler.device.Id,
1579 "intf-id": intfID,
1580 "onu-id": flow.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001581 //for _, f := range *existingFlows {
1582 // flows = append(flows, f)
1583 //}
1584 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001585 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001586 logger.Debugw(ctx, "updated-flows-for-given-flowID-and-onuid",
Shrey Baid26912972020-04-16 21:02:31 +05301587 log.Fields{
1588 "updatedflow": flows,
1589 "flow-id": flow.FlowId,
1590 "onu-id": flow.OnuId,
1591 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +05301592 return &flows
1593}
1594
npujarec5762e2020-01-01 14:08:48 +05301595func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(ctx context.Context, intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001596 logger.Debugw(ctx, "storing-flow(s)-into-kv-store", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301597 "flow-id": flowID,
1598 "device-id": f.deviceHandler.device.Id,
1599 "intf-id": intfID,
1600 "onu-id": onuID})
npujarec5762e2020-01-01 14:08:48 +05301601 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001602 logger.Warnw(ctx, "error-while-storing-flow-into-kv-store", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301603 "device-id": f.deviceHandler.device.Id,
1604 "onu-id": onuID,
1605 "intf-id": intfID,
1606 "flow-id": flowID})
manikkaraj k17652a72019-05-06 09:06:36 -04001607 return err
1608 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001609 logger.Infow(ctx, "stored-flow(s)-into-kv-store-successfully!", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301610 "device-id": f.deviceHandler.device.Id,
1611 "onu-id": onuID,
1612 "intf-id": intfID,
1613 "flow-id": flowID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301614 return nil
1615}
1616
David K. Bainbridge794735f2020-02-11 21:01:37 -08001617func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001618
1619 var intfID uint32
1620 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1621 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1622 */
1623 if deviceFlow.AccessIntfId != -1 {
1624 intfID = uint32(deviceFlow.AccessIntfId)
1625 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001626 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001627 intfID = uint32(deviceFlow.NetworkIntfId)
1628 }
1629
Neha Sharma96b7bf22020-06-15 10:37:32 +00001630 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301631 "flow": *deviceFlow,
1632 "device-id": f.deviceHandler.device.Id,
1633 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001634 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001635
1636 st, _ := status.FromError(err)
1637 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001638 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001639 "err": err,
1640 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301641 "device-id": f.deviceHandler.device.Id,
1642 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001643 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301644 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001645
1646 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001647 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301648 log.Fields{"err": err,
1649 "device-flow": deviceFlow,
1650 "device-id": f.deviceHandler.device.Id,
1651 "intf-id": intfID})
npujarec5762e2020-01-01 14:08:48 +05301652 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001653 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001654 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301655 if deviceFlow.GemportId != -1 {
1656 // No need to register the flow if it is a trap on nni flow.
Kent Hagermane6ff1012020-07-14 15:07:53 -04001657 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1658 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1659 return err
1660 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301661 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001662 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301663 log.Fields{
1664 "flow": *deviceFlow,
1665 "device-id": f.deviceHandler.device.Id,
1666 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001667 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001668}
1669
Neha Sharma96b7bf22020-06-15 10:37:32 +00001670func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1671 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301672 log.Fields{
1673 "flow": *deviceFlow,
1674 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001675 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001676 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001677 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001678 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301679 log.Fields{
1680 "err": err,
1681 "deviceFlow": deviceFlow,
1682 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001683 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001684 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001685 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001686 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001687
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001688 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001689 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001690 "of-flow-id": ofFlowID,
1691 "flow": *deviceFlow,
1692 "device-id": f.deviceHandler.device.Id,
1693 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001694 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301695}
1696
David K. Bainbridge794735f2020-02-11 21:01:37 -08001697func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001698
1699 classifierInfo := make(map[string]interface{})
1700 actionInfo := make(map[string]interface{})
1701
1702 classifierInfo[EthType] = uint32(LldpEthType)
1703 classifierInfo[PacketTagType] = Untagged
1704 actionInfo[TrapToHost] = true
1705
1706 // LLDP flow is installed to trap LLDP packets on the NNI port.
1707 // We manage flow_id resource pool on per PON port basis.
1708 // Since this situation is tricky, as a hack, we pass the NNI port
1709 // index (network_intf_id) as PON port Index for the flow_id resource
1710 // pool. Also, there is no ONU Id available for trapping LLDP packets
1711 // on NNI port, use onu_id as -1 (invalid)
1712 // ****************** CAVEAT *******************
1713 // This logic works if the NNI Port Id falls within the same valid
1714 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1715 // we need to have a re-look at this.
1716 // *********************************************
1717
1718 var onuID = -1
1719 var uniID = -1
1720 var gemPortID = -1
1721
Neha Sharma96b7bf22020-06-15 10:37:32 +00001722 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001723 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301724 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001725 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001726 var flowStoreCookie = getFlowStoreCookie(ctx, classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301727 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001728 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001729 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001730 }
npujarec5762e2020-01-01 14:08:48 +05301731 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001732
1733 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301734 return olterrors.NewErrNotFound("flow-id",
1735 log.Fields{
1736 "interface-id": networkInterfaceID,
1737 "onu-id": onuID,
1738 "uni-id": uniID,
1739 "gem-port-id": gemPortID,
1740 "cookie": flowStoreCookie,
1741 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001742 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001743 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001744 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1745 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301746 return olterrors.NewErrInvalidValue(
1747 log.Fields{
1748 "classifier": classifierInfo,
1749 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001750 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001751 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301752 log.Fields{
1753 "classifier": *classifierProto,
1754 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001755 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001756 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301757 return olterrors.NewErrInvalidValue(
1758 log.Fields{
1759 "action": actionInfo,
1760 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001761 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001762 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301763 log.Fields{
1764 "action": *actionProto,
1765 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001766
1767 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1768 OnuId: int32(onuID), // OnuId not required
1769 UniId: int32(uniID), // UniId not used
1770 FlowId: flowID,
1771 FlowType: Downstream,
1772 NetworkIntfId: int32(networkInterfaceID),
1773 GemportId: int32(gemPortID),
1774 Classifier: classifierProto,
1775 Action: actionProto,
1776 Priority: int32(flow.Priority),
1777 Cookie: flow.Cookie,
1778 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001779 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301780 return olterrors.NewErrFlowOp("add", flowID,
1781 log.Fields{
1782 "flow": downstreamflow,
1783 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001784 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001785 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301786 log.Fields{
1787 "device-id": f.deviceHandler.device.Id,
1788 "onu-id": onuID,
1789 "flow-id": flowID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001790 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1791 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1792 int32(onuID),
1793 int32(uniID),
1794 flowID, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301795 return olterrors.NewErrPersistence("update", "flow", flowID,
1796 log.Fields{
1797 "flow": downstreamflow,
1798 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001799 }
1800 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301801}
1802
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001803func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1804 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001805}
1806
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001807//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001808func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001809 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1810 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1811 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001812 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301813 log.Fields{
1814 "intf-id": intfID,
1815 "onu-id": onuID,
1816 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001817 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001818 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301819 return nil, olterrors.NewErrNotFound("onu-child-device",
1820 log.Fields{
1821 "onu-id": onuID,
1822 "intf-id": intfID,
1823 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001824 }
1825 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1826 //better to ad the device to cache here.
1827 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1828 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001829 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301830 log.Fields{
1831 "intf-id": intfID,
1832 "onu-id": onuID,
1833 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001834 }
1835
1836 return onuDev.(*OnuDevice), nil
1837}
1838
1839//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001840func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1841 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301842 log.Fields{
1843 "pon-port": intfID,
1844 "onu-id": onuID,
1845 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001846 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001847 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001848 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301849 return nil, olterrors.NewErrNotFound("onu",
1850 log.Fields{
1851 "interface-id": parentPortNo,
1852 "onu-id": onuID,
1853 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001854 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301855 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001856 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301857 log.Fields{
1858 "device-id": f.deviceHandler.device.Id,
1859 "child_device_id": onuDevice.Id,
1860 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301861 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301862}
1863
Neha Sharma96b7bf22020-06-15 10:37:32 +00001864func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1865 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301866 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001867 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301868 log.Fields{
1869 "intf-id": intfID,
1870 "onu-id": onuID,
1871 "uni-id": uniID,
1872 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001873 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301874 }
1875
1876 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001877 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301878 log.Fields{
1879 "msg": *delGemPortMsg,
1880 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001881 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301882 delGemPortMsg,
1883 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301884 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001885 onuDev.deviceType,
1886 onuDev.deviceID,
1887 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301888 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1889 log.Fields{
1890 "from-adapter": f.deviceHandler.device.Type,
1891 "to-adapter": onuDev.deviceType,
1892 "onu-id": onuDev.deviceID,
1893 "proxyDeviceID": onuDev.proxyDeviceID,
1894 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301895 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001896 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301897 log.Fields{
1898 "msg": delGemPortMsg,
1899 "from-adapter": f.deviceHandler.device.Type,
1900 "to-adapter": onuDev.deviceType,
1901 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301902 return nil
1903}
1904
Neha Sharma96b7bf22020-06-15 10:37:32 +00001905func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1906 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301907 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001908 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301909 log.Fields{
1910 "intf-id": intfID,
1911 "onu-id": onuID,
1912 "uni-id": uniID,
1913 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001914 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301915 }
1916
1917 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001918 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301919 log.Fields{
1920 "msg": *delTcontMsg,
1921 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001922 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301923 delTcontMsg,
1924 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301925 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001926 onuDev.deviceType,
1927 onuDev.deviceID,
1928 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301929 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1930 log.Fields{
1931 "from-adapter": f.deviceHandler.device.Type,
1932 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1933 "proxyDeviceID": onuDev.proxyDeviceID,
1934 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301935 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001936 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301937 log.Fields{
1938 "msg": delTcontMsg,
1939 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301940 return nil
1941}
1942
Girish Gowdrac3037402020-01-22 20:29:53 +05301943// Once the gemport is released for a given onu, it also has to be cleared from local cache
1944// which was used for deriving the gemport->logicalPortNo during packet-in.
1945// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1946// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001947func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001948
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001949 f.onuGemInfoLock.Lock()
1950 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001951
Neha Sharma96b7bf22020-06-15 10:37:32 +00001952 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301953 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001954 "gem-port-id": gemPortID,
1955 "intf-id": intfID,
1956 "onu-id": onuID,
1957 "device-id": f.deviceHandler.device.Id,
1958 "onu-gem": f.onuGemInfo[intfID]})
Girish Gowdra9602eb42020-09-09 15:50:39 -07001959
Girish Gowdrac3037402020-01-22 20:29:53 +05301960 onugem := f.onuGemInfo[intfID]
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001961deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001962 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301963 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001964 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301965 // If the gemport is found, delete it from local cache.
1966 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001967 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1968 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001969 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301970 log.Fields{
1971 "intf-id": intfID,
1972 "onu-id": onuID,
1973 "deletedgemport-id": gemPortID,
1974 "gemports": onu.GemPorts,
1975 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001976 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301977 }
1978 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001979 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301980 }
1981 }
1982}
1983
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301984//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001985// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301986func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301987 gemPortID int32, flowID uint32, flowDirection string,
1988 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001989
Neha Sharma96b7bf22020-06-15 10:37:32 +00001990 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001991 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301992 return olterrors.NewErrNotFound("tp-id",
1993 log.Fields{
1994 "flow": flow,
1995 "intf": Intf,
1996 "onu-id": onuID,
1997 "uni-id": uniID,
1998 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001999 }
Gamze Abakafee36392019-10-03 11:17:24 +00002000
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002001 if len(updatedFlows) >= 0 {
2002 // There are still flows referencing the same flow_id.
2003 // So the flow should not be freed yet.
2004 // For ex: Case of HSIA where same flow is shared
2005 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00002006 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002007 _ = olterrors.NewErrPersistence("update", "flow", flowID,
Shrey Baid26912972020-04-16 21:02:31 +05302008 log.Fields{
2009 "flow": updatedFlows,
2010 "device-id": f.deviceHandler.device.Id}, err).Log()
Girish Kumarf26e4882020-03-05 06:49:10 +00002011 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002012 if len(updatedFlows) == 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002013 logger.Debugw(ctx, "releasing-flow-id-to-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302014 log.Fields{
2015 "Intf": Intf,
2016 "onu-id": onuID,
2017 "uni-id": uniID,
2018 "flow-id": flowID,
2019 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302020 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002021
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002022 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002023 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
2024 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
Shrey Baid26912972020-04-16 21:02:31 +05302025 log.Fields{
2026 "TP-PATH": tpPath,
2027 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302028 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00002029 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +05302030 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
2031 log.Fields{
2032 "tp-id": tpID,
2033 "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002034 }
2035
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302036 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002037 used, err := f.isGemPortUsedByAnotherFlow(ctx, gemPK)
2038 if err != nil {
2039 return err
2040 }
2041 if used {
2042 if f.perGemPortLock.TryLock(gemPK) {
2043 flowIDs := f.flowsUsedByGemPort[gemPK]
2044 for i, flowIDinMap := range flowIDs {
2045 if flowIDinMap == flowID {
2046 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
2047 // everytime flowsUsedByGemPort cache is updated the same should be updated
2048 // in kv store by calling UpdateFlowIDsForGem
2049 f.flowsUsedByGemPort[gemPK] = flowIDs
2050 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs); err != nil {
2051 return err
2052 }
2053 break
Kent Hagermane6ff1012020-07-14 15:07:53 -04002054 }
Gamze Abakafee36392019-10-03 11:17:24 +00002055 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002056 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
2057 log.Fields{
2058 "gemport-id": gemPortID,
2059 "usedByFlows": flowIDs,
2060 "device-id": f.deviceHandler.device.Id})
2061 f.perGemPortLock.Unlock(gemPK)
2062 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00002063 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002064
2065 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
Shrey Baid26912972020-04-16 21:02:31 +05302066 log.Fields{
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002067 "gemport-id": gemPortID,
2068 "device-id": f.deviceHandler.device.Id,
2069 "key": gemPK,
2070 })
2071 return olterrors.NewErrAdapter("failed-to-acquire-per-gem-port-lock", log.Fields{
2072 "gemport-id": gemPortID,
2073 "device-id": f.deviceHandler.device.Id,
2074 "key": gemPK,
2075 }, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00002076 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002077 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05302078 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002079 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
2080 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
npujarec5762e2020-01-01 14:08:48 +05302081 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002082 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002083 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302084 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
2085 // by calling DeleteFlowIDsForGem
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002086 if f.perGemPortLock.TryLock(gemPK) {
2087 delete(f.flowsUsedByGemPort, gemPK)
2088 f.perGemPortLock.Unlock(gemPK)
2089 } else {
2090 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
2091 log.Fields{
2092 "device-id": f.deviceHandler.device.Id,
2093 "key": gemPK,
2094 })
2095 }
npujarec5762e2020-01-01 14:08:48 +05302096 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
2097 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002098 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05302099 // Delete the gem port on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002100 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
2101 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302102 log.Fields{
2103 "err": err,
2104 "intf": Intf,
2105 "onu-id": onuID,
2106 "uni-id": uniID,
2107 "device-id": f.deviceHandler.device.Id,
2108 "gemport-id": gemPortID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302109 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002110 switch techprofileInst := techprofileInst.(type) {
2111 case *tp.TechProfile:
2112 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
2113 if !ok {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002114 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
2115 logger.Warn(ctx, err)
2116 }
2117 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2118 logger.Warn(ctx, err)
2119 }
2120 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
2121 logger.Warn(ctx, err)
2122 }
2123 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
2124 logger.Warn(ctx, err)
2125 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002126 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
2127 // Delete the TCONT on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002128 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
2129 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002130 log.Fields{
2131 "intf": Intf,
2132 "onu-id": onuID,
2133 "uni-id": uniID,
2134 "device-id": f.deviceHandler.device.Id,
2135 "alloc-id": techprofileInst.UsScheduler.AllocID})
2136 }
2137 }
2138 case *tp.EponProfile:
Kent Hagermane6ff1012020-07-14 15:07:53 -04002139 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
2140 logger.Warn(ctx, err)
2141 }
2142 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2143 logger.Warn(ctx, err)
2144 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002145 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302146 // Delete the TCONT on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002147 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.AllocID), tpPath); err != nil {
2148 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302149 log.Fields{
2150 "intf": Intf,
2151 "onu-id": onuID,
2152 "uni-id": uniID,
2153 "device-id": f.deviceHandler.device.Id,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002154 "alloc-id": techprofileInst.AllocID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302155 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002156 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002157 logger.Errorw(ctx, "error-unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002158 log.Fields{
2159 "techprofileInst": techprofileInst})
Gamze Abakafee36392019-10-03 11:17:24 +00002160 }
2161 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002162 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302163 return nil
2164}
2165
David K. Bainbridge794735f2020-02-11 21:01:37 -08002166// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302167func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302168
Neha Sharma96b7bf22020-06-15 10:37:32 +00002169 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302170 log.Fields{
2171 "flowDirection": flowDirection,
2172 "flow": *flow,
2173 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002174
2175 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05302176 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002177 return
2178 }
2179
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302180 classifierInfo := make(map[string]interface{})
2181
Neha Sharma96b7bf22020-06-15 10:37:32 +00002182 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302183 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002184 logger.Error(ctx, err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302185 return
2186 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302187
David K. Bainbridge794735f2020-02-11 21:01:37 -08002188 onuID := int32(onu)
2189 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302190
2191 for _, field := range flows.GetOfbFields(flow) {
2192 if field.Type == flows.IP_PROTO {
2193 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002194 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302195 }
2196 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002197 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302198 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002199 "flow-id": flow.Id,
2200 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302201 "onu-id": onuID,
2202 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302203
2204 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2205 onuID = -1
2206 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002207 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2208 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002209 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002210 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002211 log.Fields{
2212 "port-number": inPort,
2213 "error": err})
2214 return
2215 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302216 }
npujarec5762e2020-01-01 14:08:48 +05302217 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002218 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302219 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302220 if flowInfo == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002221 logger.Debugw(ctx, "no-flowinfo-found-in-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302222 log.Fields{
2223 "intf": Intf,
2224 "onu-id": onuID,
2225 "uni-id": uniID,
2226 "flow-id": flowID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302227 return
2228 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302229
Kent Hagermane6ff1012020-07-14 15:07:53 -04002230 updatedFlows := *flowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302231 for i, storedFlow := range updatedFlows {
2232 if flow.Id == storedFlow.LogicalFlowID {
2233 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002234 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002235 // DKB
Neha Sharma96b7bf22020-06-15 10:37:32 +00002236 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2237 logger.Errorw(ctx, "failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002238 return
2239 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002240 logger.Info(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002241 "flow-id": flow.Id,
2242 "stored-flow": storedFlow,
2243 "device-id": f.deviceHandler.device.Id,
2244 "stored-flow-id": flowID,
2245 "onu-id": onuID,
2246 "intf": Intf,
2247 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08002248 //Remove the Flow from FlowInfo
2249 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
2250 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
2251 flowID, flowDirection, portNum, updatedFlows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002252 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002253 "flow-id": flow.Id,
2254 "stored-flow": storedFlow,
2255 "device-id": f.deviceHandler.device.Id,
2256 "stored-flow-id": flowID,
2257 "onu-id": onuID,
2258 "intf": Intf,
2259 })
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302260 return
2261 }
2262 }
2263 }
2264 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002265}
2266
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002267//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002268func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002269 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302270 var direction string
2271 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002272
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302273 for _, action := range flows.GetActions(flow) {
2274 if action.Type == flows.OUTPUT {
2275 if out := action.GetOutput(); out != nil {
2276 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002277 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302278 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002279 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002280 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002281 }
2282 }
2283 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002284
Girish Gowdra9602eb42020-09-09 15:50:39 -07002285 f.incrementActiveFlowRemoveCount(ctx, flow)
2286 defer f.decrementActiveFlowRemoveCount(ctx, flow)
2287
Esin Karamanccb714b2019-11-29 15:02:06 +00002288 if flows.HasGroup(flow) {
2289 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07002290 f.clearFlowFromResourceManager(ctx, flow, direction)
2291 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002292 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302293 direction = Upstream
2294 } else {
2295 direction = Downstream
2296 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302297
Neha Sharma96b7bf22020-06-15 10:37:32 +00002298 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002299 if err != nil {
2300 return err
2301 }
2302
2303 userKey := tpLockKey{intfID, onuID, uniID}
2304
2305 // Serialize flow removes on a per subscriber basis
2306 if f.perUserFlowHandleLock.TryLock(userKey) {
2307 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
2308 f.perUserFlowHandleLock.Unlock(userKey)
2309 } else {
2310 // Ideally this should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00002311 logger.Errorw(ctx, "failed-to-acquire-lock-to-remove-flow--remove-aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07002312 return errors.New("failed-to-acquire-per-user-lock")
2313 }
2314
2315 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002316}
2317
Esin Karamanae41e2b2019-12-17 18:13:13 +00002318//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2319func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2320 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2321 if ethType, ok := classifierInfo[EthType]; ok {
2322 if ethType.(uint32) == IPv4EthType {
2323 if ipProto, ok := classifierInfo[IPProto]; ok {
2324 if ipProto.(uint32) == IgmpProto {
2325 return true
2326 }
2327 }
2328 }
2329 }
2330 }
2331 return false
2332}
2333
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002334// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302335// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002336func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002337 classifierInfo := make(map[string]interface{})
2338 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002339 var UsMeterID uint32
2340 var DsMeterID uint32
2341
Neha Sharma96b7bf22020-06-15 10:37:32 +00002342 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302343 log.Fields{
2344 "flow": flow,
2345 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002346 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002347
Neha Sharma96b7bf22020-06-15 10:37:32 +00002348 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002349 if err != nil {
2350 // Error logging is already done in the called function
2351 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002352 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302353 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002354
Esin Karamanccb714b2019-11-29 15:02:06 +00002355 if flows.HasGroup(flow) {
2356 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002357 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002358 }
2359
manikkaraj k17652a72019-05-06 09:06:36 -04002360 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002361 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002362 if err != nil {
2363 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002364 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002365 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002366
Neha Sharma96b7bf22020-06-15 10:37:32 +00002367 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302368 log.Fields{
2369 "classifierinfo_inport": classifierInfo[InPort],
2370 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002371 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002372
Humera Kouser94d7a842019-08-25 19:04:32 -04002373 if ethType, ok := classifierInfo[EthType]; ok {
2374 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002375 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002376 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002377 }
2378 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002379 if ipProto, ok := classifierInfo[IPProto]; ok {
2380 if ipProto.(uint32) == IPProtoDhcp {
2381 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302382 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002383 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002384 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002385 }
2386 }
2387 }
2388 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002389 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002390 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002391 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002392 }
A R Karthick1f85b802019-10-11 05:06:05 +00002393
Girish Gowdra9602eb42020-09-09 15:50:39 -07002394 // If we are here it is not a trap-from-nni flow, i.e., it is subscriber specific flow.
2395 // Wait for any FlowRemoves for that specific subscriber to finish first
2396 // The goal here is to serialize FlowRemove and FlowAdd. FlowRemove take priority
2397 f.waitForFlowRemoveToFinish(ctx, flow)
2398
npujarec5762e2020-01-01 14:08:48 +05302399 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002400
Neha Sharma96b7bf22020-06-15 10:37:32 +00002401 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002402 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302403 return olterrors.NewErrNotFound("tpid-for-flow",
2404 log.Fields{
2405 "flow": flow,
2406 "intf-id": IntfID,
2407 "onu-id": onuID,
2408 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002409 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002410 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302411 log.Fields{
2412 "tp-id": TpID,
2413 "intf-id": intfID,
2414 "onu-id": onuID,
2415 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002416 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002417 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002418 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002419 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002420 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002421 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002422
2423 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002424 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
2425}
Girish Gowdra3d633032019-12-10 16:37:05 +05302426
Girish Gowdra9602eb42020-09-09 15:50:39 -07002427//WaitForFlowRemoveToFinishForSubscriber blocks until flow removes are complete for a given subscriber
2428func (f *OpenOltFlowMgr) WaitForFlowRemoveToFinishForSubscriber(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) {
2429 var flowRemoveData pendingFlowRemoveData
2430 var ok bool
2431
2432 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
2433 logger.Debugw(ctx, "wait-for-flow-remove-to-finish-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
2434
2435 f.pendingFlowRemoveDataPerSubscriberLock.RLock()
2436 if flowRemoveData, ok = f.pendingFlowRemoveDataPerSubscriber[key]; !ok {
2437 logger.Debugw(ctx, "no-pending-flow-to-remove", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
2438 f.pendingFlowRemoveDataPerSubscriberLock.RUnlock()
2439 return
Girish Gowdra3d633032019-12-10 16:37:05 +05302440 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002441 f.pendingFlowRemoveDataPerSubscriberLock.RUnlock()
2442
2443 // Wait for all flow removes to finish first
2444 <-flowRemoveData.allFlowsRemoved
2445
2446 logger.Debugw(ctx, "all-flows-cleared--handling-flow-add-now", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002447}
2448
Esin Karamanccb714b2019-11-29 15:02:06 +00002449// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002450func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002451 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002452 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302453 "classifier-info": classifierInfo,
2454 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002455
Esin Karaman65409d82020-03-18 10:58:18 +00002456 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002457 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002458 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002459 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002460 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
2461 //otherwise, classification is based on ipv4_dst by default.
2462 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
2463 mcastFlowClassificationByEthDst := false
2464
2465 if mcastFlowClassificationByEthDst {
2466 //replace ipDst with ethDst
2467 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
2468 flows.IsMulticastIp(ipv4Dst.(uint32)) {
2469 // replace ipv4_dst classifier with eth_dst
2470 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
2471 delete(classifierInfo, Ipv4Dst)
2472 classifierInfo[EthDst] = multicastMac
Neha Sharma96b7bf22020-06-15 10:37:32 +00002473 logger.Debugw(ctx, "multicast-ip-to-mac-conversion-success",
Shrey Baid26912972020-04-16 21:02:31 +05302474 log.Fields{
2475 "ip:": ipv4Dst.(uint32),
2476 "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002477 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002478 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002479 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002480
David K. Bainbridge794735f2020-02-11 21:01:37 -08002481 onuID := NoneOnuID
2482 uniID := NoneUniID
2483 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00002484
Neha Sharma96b7bf22020-06-15 10:37:32 +00002485 flowStoreCookie := getFlowStoreCookie(ctx, classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302486 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002487 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002488 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002489 }
npujarec5762e2020-01-01 14:08:48 +05302490 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00002491 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302492 return olterrors.NewErrNotFound("multicast-flow-id",
2493 log.Fields{
2494 "interface-id": networkInterfaceID,
2495 "onu-id": onuID,
2496 "uni-id": uniID,
2497 "gem-port-id": gemPortID,
2498 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002499 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002500 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002501 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2502 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002503 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002504 }
2505 groupID := actionInfo[GroupID].(uint32)
2506 multicastFlow := openoltpb2.Flow{
2507 FlowId: flowID,
2508 FlowType: Multicast,
2509 NetworkIntfId: int32(networkInterfaceID),
2510 GroupId: groupID,
2511 Classifier: classifierProto,
2512 Priority: int32(flow.Priority),
2513 Cookie: flow.Cookie}
2514
Kent Hagermane6ff1012020-07-14 15:07:53 -04002515 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002516 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002517 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002518 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002519 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002520 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002521 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002522 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002523 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002524 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002525 //cached group can be removed now
2526 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2527 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2528 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002529 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002530
2531 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2532 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2533 int32(onuID),
2534 int32(uniID),
2535 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002536 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002537 }
2538 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002539}
2540
Esin Karaman65409d82020-03-18 10:58:18 +00002541//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2542func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2543 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002544 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002545 if err != nil {
2546 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2547 }
2548 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002549 }
Esin Karaman65409d82020-03-18 10:58:18 +00002550 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302551 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002552 if e == nil && len(nniPorts) > 0 {
2553 return nniPorts[0], nil
2554 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302555 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002556}
2557
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002558//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002559func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002560
Neha Sharma96b7bf22020-06-15 10:37:32 +00002561 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302562 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002563 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302564 log.Fields{
2565 "intf-id": intfID,
2566 "onu-id": onuID,
2567 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002568 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302569 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002570 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002571
Neha Sharma96b7bf22020-06-15 10:37:32 +00002572 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002573 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002574 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002575 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002576 tpDownloadMsg,
2577 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302578 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002579 onuDev.deviceType,
2580 onuDev.deviceID,
2581 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002582 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302583 return olterrors.NewErrCommunication("send-techprofile-download-request",
2584 log.Fields{
2585 "from-adapter": f.deviceHandler.device.Type,
2586 "to-adapter": onuDev.deviceType,
2587 "onu-id": onuDev.deviceID,
2588 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002589 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002590 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302591 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302592}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002593
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302594//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002595func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302596
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002597 f.onuGemInfoLock.Lock()
2598 defer f.onuGemInfoLock.Unlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002599 onugem := f.onuGemInfo[intfID]
2600 // If the ONU already exists in onuGemInfo list, nothing to do
2601 for _, onu := range onugem {
2602 if onu.OnuID == onuID && onu.SerialNumber == serialNum {
2603 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2604 log.Fields{"onuID": onuID,
2605 "serialNum": serialNum})
2606 return nil
2607 }
2608 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002609
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302610 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2611 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002612 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002613 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302614 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002615 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302616 log.Fields{
2617 "intf-id": intfID,
2618 "onu-id": onuID,
2619 "serial-num": serialNum,
2620 "onu": onu,
2621 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002622 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002623}
2624
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302625//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302626func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002627
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002628 f.onuGemInfoLock.Lock()
2629 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002630
Neha Sharma96b7bf22020-06-15 10:37:32 +00002631 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302632 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002633 "gem-port-id": gemPort,
2634 "intf-id": intfID,
2635 "onu-id": onuID,
2636 "device-id": f.deviceHandler.device.Id,
2637 "onu-gem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302638 onugem := f.onuGemInfo[intfID]
2639 // update the gem to the local cache as well as to kv strore
2640 for idx, onu := range onugem {
2641 if onu.OnuID == onuID {
2642 // check if gem already exists , else update the cache and kvstore
2643 for _, gem := range onu.GemPorts {
2644 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002645 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302646 log.Fields{
2647 "gem": gemPort,
2648 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302649 return
2650 }
2651 }
2652 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2653 f.onuGemInfo[intfID] = onugem
Girish Gowdra9602eb42020-09-09 15:50:39 -07002654 break
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302655 }
2656 }
npujarec5762e2020-01-01 14:08:48 +05302657 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302658 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002659 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302660 log.Fields{
2661 "intf-id": intfID,
2662 "onu-id": onuID,
2663 "gemPort": gemPort,
2664 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002665 return
2666 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002667 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302668 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002669 "gem-port-id": gemPort,
2670 "intf-id": intfID,
2671 "onu-id": onuID,
2672 "device-id": f.deviceHandler.device.Id,
2673 "onu-gem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002674}
2675
2676// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002677
2678//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002679func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302680
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002681 f.onuGemInfoLock.RLock()
2682 defer f.onuGemInfoLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302683
Neha Sharma96b7bf22020-06-15 10:37:32 +00002684 logger.Infow(ctx, "getting-onu-id-from-gem-port-and-pon-port",
Shrey Baid26912972020-04-16 21:02:31 +05302685 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002686 "device-id": f.deviceHandler.device.Id,
2687 "onu-geminfo": f.onuGemInfo[intfID],
2688 "intf-id": intfID,
2689 "gemport-id": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302690 // get onuid from the onugem info cache
2691 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002692
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302693 for _, onu := range onugem {
2694 for _, gem := range onu.GemPorts {
2695 if gem == gemPortID {
2696 return onu.OnuID, nil
2697 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002698 }
2699 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002700 logger.Errorw(ctx, "onu-id-from-gem-port-not-found", log.Fields{
2701 "gem-port-id": gemPortID,
2702 "interface-id": intfID,
Kent Hagermane6ff1012020-07-14 15:07:53 -04002703 "all-gems-on-port": onugem,
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002704 })
Thomas Lee S94109f12020-03-03 16:39:29 +05302705 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002706 "interface-id": intfID,
2707 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00002708 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002709}
2710
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002711//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302712func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002713 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002714 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002715 var err error
2716
2717 if packetIn.IntfType == "pon" {
2718 // packet indication does not have serial number , so sending as nil
Neha Sharma96b7bf22020-06-15 10:37:32 +00002719 if onuID, err = f.getOnuIDfromGemPortMap(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002720 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002721 return logicalPortNum, err
2722 }
2723 if packetIn.PortNo != 0 {
2724 logicalPortNum = packetIn.PortNo
2725 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002726 uniID := uint32(0) // FIXME - multi-uni support
Neha Sharma96b7bf22020-06-15 10:37:32 +00002727 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002728 }
2729 // 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 +00002730 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002731 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002732 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002733 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002734 logger.Infow(ctx, "retrieved-logicalport-from-packet-in",
Shrey Baid26912972020-04-16 21:02:31 +05302735 log.Fields{
2736 "logical-port-num": logicalPortNum,
2737 "intf-type": packetIn.IntfType,
2738 "packet": hex.EncodeToString(packetIn.Pkt),
2739 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002740 return logicalPortNum, nil
2741}
2742
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002743//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002744func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002745 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002746
2747 ctag, priority, err := getCTagFromPacket(ctx, packet)
2748 if err != nil {
2749 return 0, err
2750 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302751
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002752 f.onuGemInfoLock.RLock()
2753 defer f.onuGemInfoLock.RUnlock()
Esin Karaman7fb80c22020-07-16 14:23:33 +00002754 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002755 var ok bool
2756 gemPortID, ok = f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302757 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002758 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302759 log.Fields{
2760 "pktinkey": pktInkey,
2761 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002762
2763 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002764 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302765 //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 +00002766 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302767 if err == nil {
2768 if gemPortID != 0 {
2769 f.packetInGemPort[pktInkey] = gemPortID
Neha Sharma96b7bf22020-06-15 10:37:32 +00002770 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302771 log.Fields{
2772 "pktinkey": pktInkey,
2773 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302774 return gemPortID, nil
2775 }
2776 }
Shrey Baid26912972020-04-16 21:02:31 +05302777 return uint32(0), olterrors.NewErrNotFound("gem-port",
2778 log.Fields{
2779 "pktinkey": pktInkey,
2780 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002781
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002782}
2783
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002784// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302785func installFlowOnAllGemports(ctx context.Context,
2786 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04002787 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002788 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05302789 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05302790 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302791 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002792 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04002793 args map[string]uint32,
2794 classifier map[string]interface{}, action map[string]interface{},
2795 logicalFlow *ofp.OfpFlowStats,
2796 gemPorts []uint32,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002797 TpInst interface{},
Manikkaraj kb1d51442019-07-23 10:41:02 -04002798 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00002799 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002800 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00002801 vlanID ...uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002802 logger.Debugw(ctx, "installing-flow-on-all-gem-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302803 log.Fields{
2804 "FlowType": FlowType,
2805 "gemPorts": gemPorts,
2806 "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05302807
Gamze Abaka724d0852020-03-18 12:10:24 +00002808 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
2809 // We need to trim prefix "0b", before further processing
2810 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
2811 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
2812
2813 // If a particular character in the string is set to '1', identify the index of this character from
2814 // the LSB position which marks the PCP bit consumed by the given gem port.
2815 // This PCP bit now becomes a classifier in the flow.
2816
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002817 switch TpInst := TpInst.(type) {
2818 case *tp.TechProfile:
2819 attributes := TpInst.DownstreamGemPortAttributeList
2820 if direction == Upstream {
2821 attributes = TpInst.UpstreamGemPortAttributeList
Gamze Abaka724d0852020-03-18 12:10:24 +00002822 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002823
2824 for _, gemPortAttribute := range attributes {
2825 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
2826 continue
Gamze Abaka724d0852020-03-18 12:10:24 +00002827 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002828 gemPortID := gemPortAttribute.GemportID
2829 if allPbitsMarked(gemPortAttribute.PbitMap) {
2830 classifier[VlanPcp] = uint32(VlanPCPMask)
2831 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002832 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
2833 logger.Warn(ctx, err)
2834 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002835 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002836 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
2837 logger.Warn(ctx, err)
2838 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002839 }
2840 } else {
2841 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
2842 if pbitSet == BinaryBit1 {
2843 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
2844 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002845 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
2846 logger.Warn(ctx, err)
2847 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002848 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002849 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
2850 logger.Warn(ctx, err)
2851 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002852 }
2853 }
2854 }
2855 }
2856 }
2857 case *tp.EponProfile:
2858 if direction == Upstream {
2859 attributes := TpInst.UpstreamQueueAttributeList
2860 for _, queueAttribute := range attributes {
2861 gemPortID := queueAttribute.GemportID
2862 if allPbitsMarked(queueAttribute.PbitMap) {
2863 classifier[VlanPcp] = uint32(VlanPCPMask)
Gamze Abaka724d0852020-03-18 12:10:24 +00002864 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002865 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
2866 logger.Warn(ctx, err)
2867 }
Gamze Abaka724d0852020-03-18 12:10:24 +00002868 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002869 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
2870 logger.Warn(ctx, err)
2871 }
Gamze Abaka724d0852020-03-18 12:10:24 +00002872 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002873 } else {
2874 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
2875 if pbitSet == BinaryBit1 {
2876 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
2877 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002878 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
2879 logger.Warn(ctx, err)
2880 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002881 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002882 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
2883 logger.Warn(ctx, err)
2884 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002885 }
2886 }
2887 }
2888 }
2889 }
2890 } else {
2891 attributes := TpInst.DownstreamQueueAttributeList
2892 for _, queueAttribute := range attributes {
2893 gemPortID := queueAttribute.GemportID
2894 if allPbitsMarked(queueAttribute.PbitMap) {
2895 classifier[VlanPcp] = uint32(VlanPCPMask)
2896 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002897 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
2898 logger.Warn(ctx, err)
2899 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002900 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002901 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
2902 logger.Warn(ctx, err)
2903 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002904 }
2905 } else {
2906 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
2907 if pbitSet == BinaryBit1 {
2908 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
2909 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002910 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
2911 logger.Warn(ctx, err)
2912 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002913 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002914 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
2915 logger.Warn(ctx, err)
2916 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002917 }
2918 }
2919 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05302920 }
2921 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002922 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002923 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002924 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpInst": TpInst})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002925 }
2926}
2927
Gamze Abaka724d0852020-03-18 12:10:24 +00002928func allPbitsMarked(pbitMap string) bool {
2929 for pos, pBit := range pbitMap {
2930 if pos >= 2 && pBit != BinaryBit1 {
2931 return false
2932 }
2933 }
2934 return true
2935}
2936
David K. Bainbridge794735f2020-02-11 21:01:37 -08002937func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002938 logger.Debug(ctx, "adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002939 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002940 classifier[PacketTagType] = DoubleTag
2941 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002942 /* We manage flowId resource pool on per PON port basis.
2943 Since this situation is tricky, as a hack, we pass the NNI port
2944 index (network_intf_id) as PON port Index for the flowId resource
2945 pool. Also, there is no ONU Id available for trapping DHCP packets
2946 on NNI port, use onu_id as -1 (invalid)
2947 ****************** CAVEAT *******************
2948 This logic works if the NNI Port Id falls within the same valid
2949 range of PON Port Ids. If this doesn't work for some OLT Vendor
2950 we need to have a re-look at this.
2951 *********************************************
2952 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002953 onuID := -1
2954 uniID := -1
2955 gemPortID := -1
2956 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002957 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302958 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302959 return olterrors.NewErrNotFound("nni-intreface-id",
2960 log.Fields{
2961 "classifier": classifier,
2962 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002963 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302964 }
2965
Neha Sharma96b7bf22020-06-15 10:37:32 +00002966 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302967 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002968 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002969 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002970 }
Gamze Abaka724d0852020-03-18 12:10:24 +00002971 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002972 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302973 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id",
2974 log.Fields{
2975 "interface-id": networkInterfaceID,
2976 "onu-id": onuID,
2977 "uni-id": uniID,
2978 "gem-port-id": gemPortID,
2979 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002980 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002981 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002982 classifierProto, err := makeOpenOltClassifierField(classifier)
2983 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002984 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002985 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002986 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002987 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002988 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002989 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002990 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002991 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002992 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2993 OnuId: int32(onuID), // OnuId not required
2994 UniId: int32(uniID), // UniId not used
2995 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002996 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002997 AllocId: int32(allocID), // AllocId not used
2998 NetworkIntfId: int32(networkInterfaceID),
2999 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003000 Classifier: classifierProto,
3001 Action: actionProto,
3002 Priority: int32(logicalFlow.Priority),
3003 Cookie: logicalFlow.Cookie,
3004 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003005 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003006 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003007 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003008 logger.Info(ctx, "dhcp-trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003009 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3010 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3011 int32(onuID),
3012 int32(uniID),
3013 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003014 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003015 }
3016 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003017}
salmansiddiqui7ac62132019-08-22 03:58:50 +00003018
Esin Karamanae41e2b2019-12-17 18:13:13 +00003019//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
3020func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
3021 var packetType string
3022 ovid, ivid := false, false
3023 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
3024 vid := vlanID & VlanvIDMask
3025 if vid != ReservedVlan {
3026 ovid = true
3027 }
3028 }
3029 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
3030 vid := uint32(metadata)
3031 if vid != ReservedVlan {
3032 ivid = true
3033 }
3034 }
3035 if ovid && ivid {
3036 packetType = DoubleTag
3037 } else if !ovid && !ivid {
3038 packetType = Untagged
3039 } else {
3040 packetType = SingleTag
3041 }
3042 return packetType
3043}
3044
3045//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08003046func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003047 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003048 action := make(map[string]interface{})
3049 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
3050 action[TrapToHost] = true
3051 /* We manage flowId resource pool on per PON port basis.
3052 Since this situation is tricky, as a hack, we pass the NNI port
3053 index (network_intf_id) as PON port Index for the flowId resource
3054 pool. Also, there is no ONU Id available for trapping packets
3055 on NNI port, use onu_id as -1 (invalid)
3056 ****************** CAVEAT *******************
3057 This logic works if the NNI Port Id falls within the same valid
3058 range of PON Port Ids. If this doesn't work for some OLT Vendor
3059 we need to have a re-look at this.
3060 *********************************************
3061 */
3062 onuID := -1
3063 uniID := -1
3064 gemPortID := -1
3065 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00003066 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003067 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303068 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003069 "classifier": classifier,
3070 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003071 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003072 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003073 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303074 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003075 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003076 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003077 }
npujarec5762e2020-01-01 14:08:48 +05303078 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003079 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303080 return olterrors.NewErrNotFound("igmp-flow-id",
3081 log.Fields{
3082 "interface-id": networkInterfaceID,
3083 "onu-id": onuID,
3084 "uni-id": uniID,
3085 "gem-port-id": gemPortID,
3086 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003087 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003088 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003089 classifierProto, err := makeOpenOltClassifierField(classifier)
3090 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003091 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003092 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003093 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003094 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003095 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003096 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003097 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003098 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003099 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3100 OnuId: int32(onuID), // OnuId not required
3101 UniId: int32(uniID), // UniId not used
3102 FlowId: flowID,
3103 FlowType: Downstream,
3104 AllocId: int32(allocID), // AllocId not used
3105 NetworkIntfId: int32(networkInterfaceID),
3106 GemportId: int32(gemPortID), // GemportId not used
3107 Classifier: classifierProto,
3108 Action: actionProto,
3109 Priority: int32(logicalFlow.Priority),
3110 Cookie: logicalFlow.Cookie,
3111 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003112 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003113 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003114 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003115 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003116 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3117 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3118 int32(onuID),
3119 int32(uniID),
3120 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003121 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003122 }
3123 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003124}
3125
salmansiddiqui7ac62132019-08-22 03:58:50 +00003126func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
3127 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05303128 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003129 }
3130 if Dir == tp_pb.Direction_UPSTREAM {
3131 return "upstream", nil
3132 } else if Dir == tp_pb.Direction_DOWNSTREAM {
3133 return "downstream", nil
3134 }
3135 return "", nil
3136}
3137
Kent Hagermane6ff1012020-07-14 15:07:53 -04003138// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303139func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003140 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003141 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00003142 var gemPort uint32
3143 intfID := args[IntfID]
3144 onuID := args[OnuID]
3145 uniID := args[UniID]
3146 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003147 allocID := args[AllocID]
salmansiddiqui7ac62132019-08-22 03:58:50 +00003148 if ipProto, ok := classifierInfo[IPProto]; ok {
3149 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003150 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003151 "tp-id": tpID,
3152 "alloc-id": allocID,
3153 "intf-id": intfID,
3154 "onu-id": onuID,
3155 "uni-id": uniID,
3156 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003157 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003158 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003159 tp_pb.Direction_UPSTREAM,
3160 pcp.(uint32))
3161 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00003162
Kent Hagermane6ff1012020-07-14 15:07:53 -04003163 if err := f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3164 logger.Warn(ctx, err)
3165 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003166 } else {
3167 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003168 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003169 }
3170
Girish Gowdra32625212020-04-29 11:26:35 -07003171 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003172 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05303173 log.Fields{
3174 "intf-id": intfID,
3175 "onu-id": onuID,
3176 "uni-id": uniID,
3177 "classifier-info:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003178 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003179 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
Esin Karamanae41e2b2019-12-17 18:13:13 +00003180 tp_pb.Direction_UPSTREAM,
3181 pcp.(uint32))
Kent Hagermane6ff1012020-07-14 15:07:53 -04003182 if err := f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3183 logger.Warn(ctx, err)
3184 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00003185 } else {
3186 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003187 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003188 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003189 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003190 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003191 return
3192 }
3193 } else if ethType, ok := classifierInfo[EthType]; ok {
3194 if ethType.(uint32) == EapEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003195 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003196 "intf-id": intfID,
3197 "onu-id": onuID,
3198 "uni-id": uniID,
3199 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003200 var vlanID uint32
3201 if val, ok := classifierInfo[VlanVid]; ok {
3202 vlanID = (val.(uint32)) & VlanvIDMask
3203 } else {
3204 vlanID = DefaultMgmtVlan
3205 }
3206 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003207 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003208 tp_pb.Direction_UPSTREAM,
3209 pcp.(uint32))
3210
Kent Hagermane6ff1012020-07-14 15:07:53 -04003211 if err := f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID); err != nil {
3212 logger.Warn(ctx, err)
3213 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003214 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003215 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003216 }
3217 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003218 } else if _, ok := actionInfo[PushVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003219 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003220 "intf-id": intfID,
3221 "onu-id": onuID,
3222 "uni-id": uniID,
3223 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003224 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003225 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003226 tp_pb.Direction_UPSTREAM,
3227 pcp.(uint32))
3228 //Adding HSIA upstream flow
Kent Hagermane6ff1012020-07-14 15:07:53 -04003229 if err := f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3230 logger.Warn(ctx, err)
3231 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003232 } else {
3233 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003234 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003235 }
3236 } else if _, ok := actionInfo[PopVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003237 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003238 "intf-id": intfID,
3239 "onu-id": onuID,
3240 "uni-id": uniID,
3241 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003242 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003243 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05003244 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003245 pcp.(uint32))
3246 //Adding HSIA downstream flow
Kent Hagermane6ff1012020-07-14 15:07:53 -04003247 if err := f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3248 logger.Warn(ctx, err)
3249 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003250 } else {
3251 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003252 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003253 }
3254 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003255 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05303256 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003257 "intf-id": intfID,
3258 "onu-id": onuID,
3259 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05303260 "classifier": classifierInfo,
3261 "action": actionInfo,
3262 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003263 return
3264 }
3265 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04003266 go func() {
3267 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
3268 logger.Warn(ctx, err)
3269 }
3270 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003271}
3272
Matteo Scandolo738c52a2020-08-03 11:14:22 -07003273func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(ctx context.Context, gemPK gemPortKey) (bool, error) {
3274 if f.perGemPortLock.TryLock(gemPK) {
3275 flowIDList := f.flowsUsedByGemPort[gemPK]
3276 f.perGemPortLock.Unlock(gemPK)
3277 return len(flowIDList) > 1, nil
3278 }
3279 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
3280 log.Fields{
3281 "device-id": f.deviceHandler.device.Id,
3282 "key": gemPK,
3283 })
3284 return false, olterrors.NewErrAdapter("failed-to-acquire-per-gem-port-lock", log.Fields{
3285 "device-id": f.deviceHandler.device.Id,
3286 "key": gemPK,
3287 }, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003288}
3289
npujarec5762e2020-01-01 14:08:48 +05303290func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3291 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003292 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3293 for _, currentGemPort := range currentGemPorts {
3294 for _, tpGemPort := range tpGemPorts {
3295 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3296 return true, currentGemPort
3297 }
3298 }
3299 }
Girish Gowdra54934262019-11-13 14:19:55 +05303300 if tpInst.InstanceCtrl.Onu == "single-instance" {
3301 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Kent Hagermane6ff1012020-07-14 15:07:53 -04003302 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID); err != nil {
3303 logger.Warn(ctx, err)
3304 }
3305 if err := f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
3306 logger.Warn(ctx, err)
3307 }
Girish Gowdra54934262019-11-13 14:19:55 +05303308
3309 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3310 // still be used on other uni ports.
3311 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3312 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003313 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003314 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303315 for i := 0; i < len(tpInstances); i++ {
3316 tpI := tpInstances[i]
3317 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303318 for _, tpGemPort := range tpGemPorts {
3319 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003320 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303321 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303322 }
3323 }
3324 }
3325 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003326 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003327 return false, 0
3328}
3329
Neha Sharma96b7bf22020-06-15 10:37:32 +00003330func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003331 for _, field := range flows.GetOfbFields(flow) {
3332 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003333 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003334 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003335 } else if field.Type == flows.ETH_DST {
3336 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003337 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003338 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003339 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003340 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003341 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003342 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003343 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003344 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303345 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003346 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003347 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003348 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003349 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003350 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003351 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003352 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003353 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003354 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003355 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003356 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003357 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003358 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003359 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003360 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003361 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003362 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003363 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003364 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003365 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003366 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003367 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003368 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003369 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003370 return
3371 }
3372 }
3373}
3374
Neha Sharma96b7bf22020-06-15 10:37:32 +00003375func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003376 for _, action := range flows.GetActions(flow) {
3377 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003378 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003379 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003380 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003381 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003382 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003383 }
Scott Baker355d1742019-10-24 10:57:52 -07003384 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003385 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003386 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003387 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003388 if out := action.GetPush(); out != nil {
3389 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003390 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003391 } else {
3392 actionInfo[PushVlan] = true
3393 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003394 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303395 log.Fields{
3396 "push-tpid": actionInfo[TPID].(uint32),
3397 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003398 }
3399 }
Scott Baker355d1742019-10-24 10:57:52 -07003400 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003401 if out := action.GetSetField(); out != nil {
3402 if field := out.GetField(); field != nil {
3403 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003404 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003405 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003406 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3407 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003408 }
3409 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003410 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003411 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003412 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003413 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003414 }
3415 }
3416 return nil
3417}
3418
Neha Sharma96b7bf22020-06-15 10:37:32 +00003419func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003420 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003421 fieldtype := ofbField.GetType()
3422 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003423 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3424 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003425 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003426 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003427 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003428 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003429 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3430 pcp := ofbField.GetVlanPcp()
3431 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003432 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003433 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003434 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003435 }
3436 }
3437}
3438
Neha Sharma96b7bf22020-06-15 10:37:32 +00003439func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003440 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003441 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003442 } else {
3443 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003444 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003445 }
3446}
3447
Neha Sharma96b7bf22020-06-15 10:37:32 +00003448func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003449 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003450 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003451 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3452 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003453 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003454 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003455 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303456 log.Fields{
3457 "newinport": classifierInfo[InPort].(uint32),
3458 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003459 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303460 return olterrors.NewErrNotFound("child-in-port",
3461 log.Fields{
3462 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3463 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003464 }
3465 }
3466 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003467 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003468 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003469 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003470 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003471 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003472 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303473 log.Fields{
3474 "newoutport": actionInfo[Output].(uint32),
3475 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003476 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303477 return olterrors.NewErrNotFound("out-port",
3478 log.Fields{
3479 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3480 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003481 }
3482 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3483 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003484 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003485 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003486 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303487 log.Fields{
3488 "newinport": actionInfo[Output].(uint32),
3489 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003490 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303491 return olterrors.NewErrNotFound("nni-port",
3492 log.Fields{
3493 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3494 "in-port": classifierInfo[InPort].(uint32),
3495 "out-port": actionInfo[Output].(uint32),
3496 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003497 }
3498 }
3499 }
3500 return nil
3501}
Gamze Abakafee36392019-10-03 11:17:24 +00003502
Neha Sharma96b7bf22020-06-15 10:37:32 +00003503func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003504 /* Metadata 8 bytes:
3505 Most Significant 2 Bytes = Inner VLAN
3506 Next 2 Bytes = Tech Profile ID(TPID)
3507 Least Significant 4 Bytes = Port ID
3508 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3509 subscriber related flows.
3510 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003511 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003512 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003513 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003514 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003515 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003516 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003517}
3518
3519func appendUnique(slice []uint32, item uint32) []uint32 {
3520 for _, sliceElement := range slice {
3521 if sliceElement == item {
3522 return slice
3523 }
3524 }
3525 return append(slice, item)
3526}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303527
3528// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003529func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303530
3531 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3532 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003533 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003534 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003535 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003536 log.Fields{
3537 "port-number": action[Output].(uint32),
3538 "error": err})
3539 return uint32(0), err
3540 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003541 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303542 return intfID, nil
3543 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003544 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003545 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003546 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003547 log.Fields{
3548 "port-number": action[Output].(uint32),
3549 "error": err})
3550 return uint32(0), err
3551 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003552 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303553 return intfID, nil
3554 }
3555 return uint32(0), nil
3556}
3557
3558// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003559func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3560 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3561 if err != nil {
3562 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3563 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3564 return
3565 }
3566 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003567
3568 f.onuGemInfoLock.Lock()
3569 defer f.onuGemInfoLock.Unlock()
3570
Matt Jeanneret1719a072019-12-20 14:50:14 -05003571 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303572 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003573 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003574 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 +05303575 log.Fields{
3576 "pktinkey": pktInkey,
3577 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003578 return
3579 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303580 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003581 f.packetInGemPort[pktInkey] = gemPort
3582
npujarec5762e2020-01-01 14:08:48 +05303583 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003584 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 +05303585 log.Fields{
3586 "pktinkey": pktInkey,
3587 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303588}
3589
Esin Karaman7fb80c22020-07-16 14:23:33 +00003590//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3591func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3592 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003593 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003594 return 0, 0, errors.New("invalid packet length")
3595 }
3596 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3597 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3598
3599 var index int8
3600 if outerEthType == 0x8100 {
3601 if innerEthType == 0x8100 {
3602 // q-in-q 802.1ad or 802.1q double tagged packet.
3603 // get the inner vlanId
3604 index = 18
3605 } else {
3606 index = 14
3607 }
3608 priority := (packet[index] >> 5) & 0x7
3609 //13 bits composes vlanId value
3610 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3611 return vlan, priority, nil
3612 }
3613 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3614 return 0, 0, nil
3615}
3616
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303617// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303618func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003619
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003620 f.onuGemInfoLock.Lock()
3621 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003622
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303623 onugem := f.onuGemInfo[intfID]
3624 for idx, onu := range onugem {
3625 if onu.OnuID == onuID {
3626 for _, uni := range onu.UniPorts {
3627 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003628 logger.Infow(ctx, "uni-already-in-cache--no-need-to-update-cache-and-kv-store", log.Fields{"uni": portNum})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303629 return
3630 }
3631 }
3632 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3633 f.onuGemInfo[intfID] = onugem
3634 }
3635 }
npujarec5762e2020-01-01 14:08:48 +05303636 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003637
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303638}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303639
npujarec5762e2020-01-01 14:08:48 +05303640func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3641 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303642 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003643 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303644 return
3645 }
3646 for gem, FlowIDs := range flowIDsList {
3647 gemPK := gemPortKey{intf, uint32(gem)}
Matteo Scandolo738c52a2020-08-03 11:14:22 -07003648 if f.perGemPortLock.TryLock(gemPK) {
3649 f.flowsUsedByGemPort[gemPK] = FlowIDs
3650 f.perGemPortLock.Unlock(gemPK)
3651 } else {
3652 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
3653 log.Fields{
3654 "intf-id": intf,
3655 "device-id": f.deviceHandler.device.Id,
3656 "key": gemPK,
3657 })
3658 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303659 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303660}
Esin Karamanccb714b2019-11-29 15:02:06 +00003661
Girish Gowdra9602eb42020-09-09 15:50:39 -07003662//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3663// clears resources reserved for this multicast flow
3664func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
3665 classifierInfo := make(map[string]interface{})
3666 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
3667 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
3668
Esin Karamanccb714b2019-11-29 15:02:06 +00003669 if err != nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003670 logger.Warnw(ctx, "no-inport-found--cannot-release-resources-of-the-multicast-flow", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00003671 return
3672 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003673
3674 var onuID = int32(NoneOnuID)
3675 var uniID = int32(NoneUniID)
3676 var flowID uint32
3677
3678 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
3679
3680 for _, flowID = range flowIds {
3681 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
3682 if flowInfo == nil {
3683 logger.Debugw(ctx, "no-multicast-flowinfo-found-in-the-kv-store",
3684 log.Fields{
3685 "intf": networkInterfaceID,
3686 "onu-id": onuID,
3687 "uni-id": uniID,
3688 "flow-id": flowID})
3689 continue
Esin Karamanccb714b2019-11-29 15:02:06 +00003690 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003691 updatedFlows := *flowInfo
3692 for i, storedFlow := range updatedFlows {
3693 if flow.Id == storedFlow.LogicalFlowID {
3694 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
3695 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3696 log.Fields{
3697 "flow": storedFlow,
3698 "flow-id": flow.Id,
3699 "device-id": f.deviceHandler.device.Id})
3700 //remove from device
3701 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3702 // DKB
3703 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3704 log.Fields{
3705 "flow-id": flow.Id,
3706 "error": err})
3707 return
3708 }
3709 logger.Infow(ctx, "multicast-flow-removed-from-device-successfully", log.Fields{"flow-id": flow.Id})
3710 //Remove the Flow from FlowInfo
3711 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
3712 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
3713 logger.Errorw(ctx, "failed-to-delete-multicast-flow-from-the-kv-store",
3714 log.Fields{"flow": storedFlow,
3715 "err": err})
3716 return
3717 }
3718 //release flow id
3719 logger.Debugw(ctx, "releasing-multicast-flow-id",
3720 log.Fields{"flow-id": flowID,
3721 "interfaceID": networkInterfaceID})
3722 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
3723 }
3724 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003725 }
3726}
3727
Girish Gowdra9602eb42020-09-09 15:50:39 -07003728func (f *OpenOltFlowMgr) incrementActiveFlowRemoveCount(ctx context.Context, flow *ofp.OfpFlowStats) {
3729 inPort, outPort := getPorts(flow)
3730 logger.Debugw(ctx, "increment-flow-remove-count-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
3731 if inPort != InvalidPort && outPort != InvalidPort {
3732 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
3733 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
3734 logger.Debugw(ctx, "increment-flow-remove-count-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3735
3736 f.pendingFlowRemoveDataPerSubscriberLock.Lock()
3737 defer f.pendingFlowRemoveDataPerSubscriberLock.Unlock()
3738 flowRemoveData, ok := f.pendingFlowRemoveDataPerSubscriber[key]
3739 if !ok {
3740 flowRemoveData = pendingFlowRemoveData{
3741 pendingFlowRemoveCount: 0,
3742 allFlowsRemoved: make(chan struct{}),
3743 }
3744 }
3745 flowRemoveData.pendingFlowRemoveCount++
3746 f.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
3747
3748 logger.Debugw(ctx, "current-flow-remove-count–increment",
3749 log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID,
3750 "currCnt": f.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
Esin Karamanccb714b2019-11-29 15:02:06 +00003751 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003752}
3753
Girish Gowdra9602eb42020-09-09 15:50:39 -07003754func (f *OpenOltFlowMgr) decrementActiveFlowRemoveCount(ctx context.Context, flow *ofp.OfpFlowStats) {
3755 inPort, outPort := getPorts(flow)
3756 logger.Debugw(ctx, "decrement-flow-remove-count-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
3757 if inPort != InvalidPort && outPort != InvalidPort {
3758 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
3759 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
3760 logger.Debugw(ctx, "decrement-flow-remove-count-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3761
3762 f.pendingFlowRemoveDataPerSubscriberLock.Lock()
3763 defer f.pendingFlowRemoveDataPerSubscriberLock.Unlock()
3764 if val, ok := f.pendingFlowRemoveDataPerSubscriber[key]; !ok {
3765 logger.Fatalf(ctx, "flow-remove-key-not-found", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3766 } else {
3767 if val.pendingFlowRemoveCount > 0 {
3768 val.pendingFlowRemoveCount--
3769 }
3770 logger.Debugw(ctx, "current-flow-remove-count-after-decrement",
3771 log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID,
3772 "currCnt": f.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
3773 // If all flow removes have finished, then close the channel to signal the receiver
3774 // to go ahead with flow adds.
3775 if val.pendingFlowRemoveCount == 0 {
3776 close(val.allFlowsRemoved)
3777 delete(f.pendingFlowRemoveDataPerSubscriber, key)
3778 return
3779 }
3780 f.pendingFlowRemoveDataPerSubscriber[key] = val
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003781 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003782 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003783}
3784
3785func (f *OpenOltFlowMgr) waitForFlowRemoveToFinish(ctx context.Context, flow *ofp.OfpFlowStats) {
3786 var flowRemoveData pendingFlowRemoveData
3787 var ok bool
3788 inPort, outPort := getPorts(flow)
3789 logger.Debugw(ctx, "wait-for-flow-remove-to-finish-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
3790 if inPort != InvalidPort && outPort != InvalidPort {
3791 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
3792 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
3793 logger.Debugw(ctx, "wait-for-flow-remove-to-finish-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3794
3795 f.pendingFlowRemoveDataPerSubscriberLock.RLock()
3796 if flowRemoveData, ok = f.pendingFlowRemoveDataPerSubscriber[key]; !ok {
3797 logger.Debugw(ctx, "no-pending-flow-to-remove", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3798 f.pendingFlowRemoveDataPerSubscriberLock.RUnlock()
3799 return
3800 }
3801 f.pendingFlowRemoveDataPerSubscriberLock.RUnlock()
3802
3803 // Wait for all flow removes to finish first
3804 <-flowRemoveData.allFlowsRemoved
3805
3806 logger.Debugw(ctx, "all-flows-cleared--handling-flow-add-now", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3807 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003808}