blob: e1bc9aa1eed80ff5f290829a67728f1cfb478f2d [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
Matteo Scandolo6056e822019-11-13 14:05:29 -080022 "encoding/hex"
Girish Gowdracefae192020-03-19 18:14:10 -070023 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "fmt"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070025 "github.com/opencord/voltha-lib-go/v4/pkg/flows"
26 "github.com/opencord/voltha-lib-go/v4/pkg/log"
27 tp "github.com/opencord/voltha-lib-go/v4/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080028 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070029 "github.com/opencord/voltha-protos/v4/go/common"
30 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
31 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
32 openoltpb2 "github.com/opencord/voltha-protos/v4/go/openolt"
33 tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
34 "github.com/opencord/voltha-protos/v4/go/voltha"
Girish Gowdra9602eb42020-09-09 15:50:39 -070035 "strings"
36 "sync"
Chaitrashree G S579fe732019-08-20 20:50:47 -040037
Girish Gowdra3d633032019-12-10 16:37:05 +053038 "github.com/EagleChen/mapmutex"
Thomas Lee S94109f12020-03-03 16:39:29 +053039 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000040 "google.golang.org/grpc/codes"
41 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053042)
43
44const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070045 //IPProtoDhcp flow category
46 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053047
Girish Gowdraa09aeab2020-09-14 16:30:52 -070048 //IgmpProto proto value
49 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070050
51 //EapEthType eapethtype value
52 EapEthType = 0x888e
53 //LldpEthType lldp ethtype value
54 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000055 //IPv4EthType IPv4 ethernet type value
56 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070057
Andrea Campanella7acc0b92020-02-14 09:20:49 +010058 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
59 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040060
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070061 //DefaultMgmtVlan default vlan value
62 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053063
manikkaraj kbf256be2019-03-25 00:13:48 +053064 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070065
David K. Bainbridge82efc492019-09-04 09:57:11 -070066 //Upstream constant
67 Upstream = "upstream"
68 //Downstream constant
69 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000070 //Multicast constant
71 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070072 //PacketTagType constant
73 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070074 //Untagged constant
75 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070076 //SingleTag constant
77 SingleTag = "single_tag"
78 //DoubleTag constant
79 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053080
81 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070082
83 //EthType constant
84 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000085 //EthDst constant
86 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087 //TPID constant
88 TPID = "tpid"
89 //IPProto constant
90 IPProto = "ip_proto"
91 //InPort constant
92 InPort = "in_port"
93 //VlanVid constant
94 VlanVid = "vlan_vid"
95 //VlanPcp constant
96 VlanPcp = "vlan_pcp"
97
98 //UDPDst constant
99 UDPDst = "udp_dst"
100 //UDPSrc constant
101 UDPSrc = "udp_src"
102 //Ipv4Dst constant
103 Ipv4Dst = "ipv4_dst"
104 //Ipv4Src constant
105 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700106 //Metadata constant
107 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108 //TunnelID constant
109 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700110 //Output constant
111 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000112 //GroupID constant
113 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 // Actions
115
116 //PopVlan constant
117 PopVlan = "pop_vlan"
118 //PushVlan constant
119 PushVlan = "push_vlan"
120 //TrapToHost constant
121 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400122 //MaxMeterBand constant
123 MaxMeterBand = 2
124 //VlanPCPMask contant
125 VlanPCPMask = 0xFF
126 //VlanvIDMask constant
127 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000128 //IntfID constant
129 IntfID = "intfId"
130 //OnuID constant
131 OnuID = "onuId"
132 //UniID constant
133 UniID = "uniId"
134 //PortNo constant
135 PortNo = "portNo"
136 //AllocID constant
137 AllocID = "allocId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000138
139 //NoneOnuID constant
140 NoneOnuID = -1
141 //NoneUniID constant
142 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700143
144 // MapMutex
145 maxRetry = 300
146 maxDelay = 100000000
147 baseDelay = 10000000
148 factor = 1.1
149 jitter = 0.2
manikkaraj kbf256be2019-03-25 00:13:48 +0530150
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700151 bitMapPrefix = "0b"
152 pbit1 = '1'
153)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400154
Girish Gowdra3d633032019-12-10 16:37:05 +0530155type tpLockKey struct {
156 intfID uint32
157 onuID uint32
158 uniID uint32
159}
160
Gamze Abakafee36392019-10-03 11:17:24 +0000161type schedQueue struct {
162 direction tp_pb.Direction
163 intfID uint32
164 onuID uint32
165 uniID uint32
166 tpID uint32
167 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700168 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000169 meterID uint32
170 flowMetadata *voltha.FlowMetadata
171}
172
Girish Gowdra9602eb42020-09-09 15:50:39 -0700173// pendingFlowRemoveDataKey is key to pendingFlowRemoveDataPerSubscriber map
174type pendingFlowRemoveDataKey struct {
175 intfID uint32
176 onuID uint32
177 uniID uint32
178}
179
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700180// subscriberDataPathFlowIDKey is key to subscriberDataPathFlowIDMap map
181type subscriberDataPathFlowIDKey struct {
182 intfID uint32
183 onuID uint32
184 uniID uint32
185 direction string
186 tpID uint32
187}
188
Girish Gowdra9602eb42020-09-09 15:50:39 -0700189// pendingFlowRemoveData is value stored in pendingFlowRemoveDataPerSubscriber map
190// This holds the number of pending flow removes and also a signal channel to
191// to indicate the receiver when all flow removes are handled
192type pendingFlowRemoveData struct {
193 pendingFlowRemoveCount uint32
194 allFlowsRemoved chan struct{}
Esin Karamanccb714b2019-11-29 15:02:06 +0000195}
196
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700197//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530198type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700199 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
200 techprofile map[uint32]tp.TechProfileIf
201 deviceHandler *DeviceHandler
202 grpMgr *OpenOltGroupMgr
203 resourceMgr *rsrcMgr.OpenOltResourceMgr
204
205 onuIdsLock sync.RWMutex // TODO: Do we need this?
206
207 flowsUsedByGemPort map[uint32][]uint64 // gem port id to flow ids
208 flowsUsedByGemPortKey sync.RWMutex // lock to be used to access the flowsUsedByGemPort map
209
210 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
211 packetInGemPortLock sync.RWMutex
212
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700213 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700214 onuGemInfo []rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700215 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700216 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700217
Girish Gowdra3d633032019-12-10 16:37:05 +0530218 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Girish Gowdra9602eb42020-09-09 15:50:39 -0700219 perUserFlowHandleLock *mapmutex.Mutex
220
221 // pendingFlowRemoveDataPerSubscriber map is used to maintain the context on a per
222 // subscriber basis for the number of pending flow removes. This data is used
223 // to process all the flow removes for a subscriber before handling flow adds.
224 // Interleaving flow delete and flow add processing has known to cause PON resource
225 // management contentions on a per subscriber bases, so we need ensure ordering.
226 pendingFlowRemoveDataPerSubscriber map[pendingFlowRemoveDataKey]pendingFlowRemoveData
227 pendingFlowRemoveDataPerSubscriberLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700228
229 // Map of voltha flowID associated with subscriberDataPathFlowIDKey
230 // This information is not persisted on Kv store and hence should be reconciled on adapter restart
231 subscriberDataPathFlowIDMap map[subscriberDataPathFlowIDKey]uint64
232 subscriberDataPathFlowIDMapLock sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530233}
234
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700235//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700236func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000237 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530238 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530239 var err error
240 var idx uint32
241
manikkaraj kbf256be2019-03-25 00:13:48 +0530242 flowMgr.deviceHandler = dh
Girish Gowdra9602eb42020-09-09 15:50:39 -0700243 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530244 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000245 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000246 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
247 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530248 return nil
249 }
William Kurkian740a09c2019-10-23 17:07:38 -0400250 flowMgr.onuIdsLock = sync.RWMutex{}
Girish Gowdra9602eb42020-09-09 15:50:39 -0700251 flowMgr.pendingFlowRemoveDataPerSubscriberLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700252 flowMgr.flowsUsedByGemPort = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530253 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700254 flowMgr.packetInGemPortLock = sync.RWMutex{}
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700255 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700256 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(maxRetry, maxDelay, baseDelay, factor, jitter)
Girish Gowdra9602eb42020-09-09 15:50:39 -0700257 flowMgr.pendingFlowRemoveDataPerSubscriber = make(map[pendingFlowRemoveDataKey]pendingFlowRemoveData)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700258 flowMgr.subscriberDataPathFlowIDMap = make(map[subscriberDataPathFlowIDKey]uint64)
259 flowMgr.subscriberDataPathFlowIDMapLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530260 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700261 if flowMgr.onuGemInfo, err = rMgr.GetOnuGemInfo(ctx, ponPortIdx); err != nil {
262 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530263 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700264 //Load flowID list per gem map per interface from the kvstore.
265 flowMgr.loadFlowIDlistForGem(ctx, idx)
Esin Karamanccb714b2019-11-29 15:02:06 +0000266 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700267 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700268 flowMgr.reconcileSubscriberDataPathFlowIDMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000269 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530270 return &flowMgr
271}
272
Kent Hagermane6ff1012020-07-14 15:07:53 -0400273func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700274 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
275 // Flow is not replicated in this case, we need to register the flow for a single gem-port
276 return f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
277 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
278 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
279 for _, gemPort := range deviceFlow.PbitToGemport {
280 if err := f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
281 return err
282 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700283 }
Gamze Abakafee36392019-10-03 11:17:24 +0000284 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700285 return nil
286}
287
288func (f *OpenOltFlowMgr) registerFlowIDForGem(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
289 f.flowsUsedByGemPortKey.Lock()
290 flowIDList, ok := f.flowsUsedByGemPort[gemPortID]
291 if !ok {
292 flowIDList = []uint64{flowFromCore.Id}
293 }
294 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
295 f.flowsUsedByGemPort[gemPortID] = flowIDList
296 f.flowsUsedByGemPortKey.Unlock()
297
298 // update the flowids for a gem to the KVstore
299 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400300}
301
Girish Gowdra9602eb42020-09-09 15:50:39 -0700302func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000303 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200304 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000305 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530306 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700307 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530308
Neha Sharma96b7bf22020-06-15 10:37:32 +0000309 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530310 "device-id": f.deviceHandler.device.Id,
311 "intf-id": intfID,
312 "onu-id": onuID,
313 "uni-id": uniID,
314 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700315 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530316 "action": actionInfo,
317 "usmeter-iD": UsMeterID,
318 "dsmeter-iD": DsMeterID,
319 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400320 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
321 // is because the flow is an NNI flow and there would be no onu resources associated with it
322 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400323 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200324 cause := "no-onu-id-for-flow"
325 fields := log.Fields{
326 "onu": onuID,
327 "port-no": portNo,
328 "classifer": classifierInfo,
329 "action": actionInfo,
330 "device-id": f.deviceHandler.device.Id}
331 logger.Errorw(ctx, cause, fields)
332 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530333 }
334
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700335 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000336 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530337 "uni": uni,
338 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530339
340 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
341 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000342 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530343 "device-id": f.deviceHandler.device.Id,
344 "intf-id": intfID,
345 "onu-id": onuID,
346 "uni-id": uniID,
347 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700348 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530349 "action": actionInfo,
350 "usmeter-id": UsMeterID,
351 "dsmeter-id": DsMeterID,
352 "tp-id": TpID})
npujarec5762e2020-01-01 14:08:48 +0530353 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530354 if allocID == 0 || gemPorts == nil || TpInst == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000355 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530356 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
Andrea Campanellabfe08432020-09-11 17:07:03 +0200357 return olterrors.NewErrNotFound(
358 "alloc-id-gem-ports-tp-unavailable",
359 nil, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +0530360 }
361 args := make(map[string]uint32)
362 args[IntfID] = intfID
363 args[OnuID] = onuID
364 args[UniID] = uniID
365 args[PortNo] = portNo
366 args[AllocID] = allocID
367
368 /* Flows can be added specific to gemport if p-bits are received.
369 * If no pbit mentioned then adding flows for all gemports
370 */
npujarec5762e2020-01-01 14:08:48 +0530371 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530372 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
373 } else {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200374 cause := "failed-to-acquire-per-user-flow-handle-lock"
375 fields := log.Fields{
376 "intf-id": intfID,
377 "onu-id": onuID,
378 "uni-id": uniID,
379 "flow-id": flow.Id,
380 "flow-cookie": flow.Cookie,
381 "device-id": f.deviceHandler.device.Id}
382 logger.Errorw(ctx, cause, fields)
383 return olterrors.NewErrAdapter(cause, fields, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400384 }
Andrea Campanellabfe08432020-09-11 17:07:03 +0200385 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530386}
387
salmansiddiqui7ac62132019-08-22 03:58:50 +0000388// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530389func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400390
Neha Sharma96b7bf22020-06-15 10:37:32 +0000391 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530392 log.Fields{"dir": sq.direction,
393 "intf-id": sq.intfID,
394 "onu-id": sq.onuID,
395 "uni-id": sq.uniID,
396 "tp-id": sq.tpID,
397 "meter-id": sq.meterID,
398 "tp-inst": sq.tpInst,
399 "flowmetadata": sq.flowMetadata,
400 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401
Gamze Abakafee36392019-10-03 11:17:24 +0000402 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000403 if err != nil {
404 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400405 }
406
407 /* Lets make a simple assumption that if the meter-id is present on the KV store,
408 * then the scheduler and queues configuration is applied on the OLT device
409 * in the given direction.
410 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000411
Manikkaraj kb1d51442019-07-23 10:41:02 -0400412 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530413 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400414 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530415 return olterrors.NewErrNotFound("meter",
416 log.Fields{"intf-id": sq.intfID,
417 "onu-id": sq.onuID,
418 "uni-id": sq.uniID,
419 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400420 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000421
Manikkaraj kb1d51442019-07-23 10:41:02 -0400422 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000423 if KvStoreMeter.MeterId == sq.meterID {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000424 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400425 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400426 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530427 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800428 "unsupported": "meter-id",
429 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530430 "meter-id-in-flow": sq.meterID,
431 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000433
Neha Sharma96b7bf22020-06-15 10:37:32 +0000434 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530435 log.Fields{
436 "meter-id": sq.meterID,
437 "direction": Direction,
438 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000439
Gamze Abakafee36392019-10-03 11:17:24 +0000440 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000441 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000442 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000443 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400444 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000445
446 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530447 return olterrors.NewErrNotFound("scheduler-config",
448 log.Fields{
449 "intf-id": sq.intfID,
450 "direction": sq.direction,
451 "tp-inst": sq.tpInst,
452 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000453 }
454
Manikkaraj kb1d51442019-07-23 10:41:02 -0400455 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000456 if sq.flowMetadata != nil {
457 for _, meter := range sq.flowMetadata.Meters {
458 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400459 meterConfig = meter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000460 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Shrey Baid26912972020-04-16 21:02:31 +0530461 log.Fields{"meterConfig": meterConfig,
462 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400463 break
464 }
465 }
466 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000467 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400468 }
469 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530470 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800471 "reason": "Could-not-get-meterbands-from-flowMetadata",
472 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530473 "meter-id": sq.meterID,
474 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400475 } else if len(meterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000476 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Shrey Baid26912972020-04-16 21:02:31 +0530477 log.Fields{"Bands": meterConfig.Bands,
478 "meter-id": sq.meterID,
479 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530480 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800481 "reason": "Invalid-number-of-bands-in-meter",
482 "meterband-count": len(meterConfig.Bands),
483 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530484 "meter-id": sq.meterID,
485 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400486 }
487 cir := meterConfig.Bands[0].Rate
488 cbs := meterConfig.Bands[0].BurstSize
489 eir := meterConfig.Bands[1].Rate
490 ebs := meterConfig.Bands[1].BurstSize
491 pir := cir + eir
492 pbs := cbs + ebs
493 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
494
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700495 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000496 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400497
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700498 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530499 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
500 log.Fields{"intf-id": sq.intfID,
501 "direction": sq.direction,
502 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503 }
504
salmansiddiqui7ac62132019-08-22 03:58:50 +0000505 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400506 * store the meter id on the KV store, for further reference.
507 */
npujarec5762e2020-01-01 14:08:48 +0530508 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 +0530509 return olterrors.NewErrAdapter("failed-updating-meter-id",
510 log.Fields{"onu-id": sq.onuID,
511 "meter-id": sq.meterID,
512 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400513 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000514 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530515 log.Fields{"direction": Direction,
516 "Meter": meterConfig,
517 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400518 return nil
519}
520
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700521func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000522 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000523
524 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530525 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
526 log.Fields{"intf-id": sq.intfID,
527 "direction": sq.direction,
528 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000529 }
530
Neha Sharma96b7bf22020-06-15 10:37:32 +0000531 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530532 log.Fields{
533 "direction": sq.direction,
534 "TrafficScheds": TrafficSched,
535 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530536 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000537 IntfId: sq.intfID, OnuId: sq.onuID,
538 UniId: sq.uniID, PortNo: sq.uniPort,
539 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000540 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000541 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000542 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530543 "direction": sq.direction,
544 "traffic-queues": trafficQueues,
545 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000546
547 // On receiving the CreateTrafficQueues request, the driver should create corresponding
548 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000549 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530550 log.Fields{"direction": sq.direction,
551 "traffic-queues": trafficQueues,
552 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530553 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000554 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
555 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000556 TrafficQueues: trafficQueues,
557 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530558 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000559 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000560 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530561 "direction": sq.direction,
562 "traffic-queues": trafficQueues,
563 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000564
Esin Karamanccb714b2019-11-29 15:02:06 +0000565 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000566 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000567 if len(multicastTrafficQueues) > 0 {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700568 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present {
Esin Karamanccb714b2019-11-29 15:02:06 +0000569 //assumed that there is only one queue per PON for the multicast service
570 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
571 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000572 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000573 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700574 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000575 gemPortID: multicastQueuePerPonPort.GemportId,
576 servicePriority: multicastQueuePerPonPort.Priority,
577 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700578 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000579 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400580 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
581 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
582 return err
583 }
Shrey Baid26912972020-04-16 21:02:31 +0530584
Neha Sharma96b7bf22020-06-15 10:37:32 +0000585 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000586 }
587 }
588 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000589 return nil
590}
591
salmansiddiqui7ac62132019-08-22 03:58:50 +0000592// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530593func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400594
595 var Direction string
596 var SchedCfg *tp_pb.SchedulerConfig
597 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000598 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530599 log.Fields{
600 "direction": sq.direction,
601 "intf-id": sq.intfID,
602 "onu-id": sq.onuID,
603 "uni-id": sq.uniID,
604 "uni-port": sq.uniPort,
605 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000606 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000607 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400608 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000609 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000610 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400611 Direction = "downstream"
612 }
613
Girish Kumar8f73fe02019-12-09 13:19:37 +0000614 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530615 return olterrors.NewErrNotFound("scheduler-config",
616 log.Fields{
617 "int-id": sq.intfID,
618 "direction": sq.direction,
619 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000620 }
621
npujarec5762e2020-01-01 14:08:48 +0530622 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400623 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530624 return olterrors.NewErrNotFound("meter",
625 log.Fields{
626 "onu-id": sq.onuID,
627 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400628 }
629 if KVStoreMeter == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000630 logger.Warnw(ctx, "no-meter-installed-yet",
Shrey Baid26912972020-04-16 21:02:31 +0530631 log.Fields{
632 "direction": Direction,
633 "intf-id": sq.intfID,
634 "onu-id": sq.onuID,
635 "uni-id": sq.uniID,
636 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400637 return nil
638 }
639 cir := KVStoreMeter.Bands[0].Rate
640 cbs := KVStoreMeter.Bands[0].BurstSize
641 eir := KVStoreMeter.Bands[1].Rate
642 ebs := KVStoreMeter.Bands[1].BurstSize
643 pir := cir + eir
644 pbs := cbs + ebs
645
646 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
647
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700648 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000649 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000650
Neha Sharma96b7bf22020-06-15 10:37:32 +0000651 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000652 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530653 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
654 log.Fields{
655 "intf-id": sq.intfID,
656 "direction": sq.direction,
657 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000658 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400659
npujarec5762e2020-01-01 14:08:48 +0530660 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000661 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
662 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000663 TrafficQueues: TrafficQueues,
664 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000665 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530666 log.Fields{
667 "intf-id": sq.intfID,
668 "traffic-queues": TrafficQueues,
669 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400670 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000671 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530672 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000673 IntfId: sq.intfID, OnuId: sq.onuID,
674 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400675 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000676 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530677 log.Fields{
678 "intf-id": sq.intfID,
679 "traffic-schedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400680 }
681
Neha Sharma96b7bf22020-06-15 10:37:32 +0000682 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000683
684 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400685 * delete the meter id on the KV store.
686 */
npujarec5762e2020-01-01 14:08:48 +0530687 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400688 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530689 return olterrors.NewErrAdapter("unable-to-remove-meter",
690 log.Fields{
691 "onu": sq.onuID,
692 "meter": KVStoreMeter.MeterId,
693 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400694 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000695 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530696 log.Fields{
697 "meter-id": KVStoreMeter.MeterId,
698 "dir": Direction,
699 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400700 return err
701}
702
Gamze Abakafee36392019-10-03 11:17:24 +0000703// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700704func (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 +0000705 var allocIDs []uint32
706 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530707 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530708 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000709 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000710
npujarec5762e2020-01-01 14:08:48 +0530711 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
712 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400713
Neha Sharma96b7bf22020-06-15 10:37:32 +0000714 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530715
Neha Sharma96b7bf22020-06-15 10:37:32 +0000716 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530717 "intf-id": intfID,
718 "onu-id": onuID,
719 "uni-id": uniID,
720 "device-id": f.deviceHandler.device.Id,
721 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530722
Manikkaraj kb1d51442019-07-23 10:41:02 -0400723 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530724 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000725 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000726 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530727 log.Fields{
728 "path": tpPath,
729 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530730 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000731 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530732 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000733 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530734 log.Fields{
735 "error": err,
736 "tp-id": TpID,
737 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000738 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530739 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400740 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
741 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
742 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530743 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000744 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530745 log.Fields{
746 "uni": uni,
747 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530748 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530749 }
Gamze Abakafee36392019-10-03 11:17:24 +0000750
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700751 switch tpInst := techProfileInstance.(type) {
752 case *tp.TechProfile:
753 if UsMeterID != 0 {
754 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
755 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
756 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000757 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700758 log.Fields{
759 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700760 "onu-id": onuID,
761 "uni-id": uniID,
762 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700763 "meter-id": UsMeterID,
764 "device-id": f.deviceHandler.device.Id})
765 return 0, nil, nil
766 }
767 }
768 if DsMeterID != 0 {
769 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
770 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
771 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000772 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700773 log.Fields{
774 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700775 "onu-id": onuID,
776 "uni-id": uniID,
777 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700778 "meter-id": DsMeterID,
779 "device-id": f.deviceHandler.device.Id})
780 return 0, nil, nil
781 }
782 }
783 allocID := tpInst.UsScheduler.AllocID
784 for _, gem := range tpInst.UpstreamGemPortAttributeList {
785 gemPortIDs = append(gemPortIDs, gem.GemportID)
786 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700787 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000788
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700789 if tpInstanceExists {
790 return allocID, gemPortIDs, techProfileInstance
791 }
792
793 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700794 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700795 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000796 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700797 log.Fields{
798 "alloc-ids": allocIDs,
799 "gemports": allgemPortIDs,
800 "device-id": f.deviceHandler.device.Id})
801 // Send Tconts and GEM ports to KV store
802 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530803 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700804 case *tp.EponProfile:
805 // CreateSchedulerQueues for EPON needs to be implemented here
806 // when voltha-protos for EPON is completed.
807 allocID := tpInst.AllocID
808 for _, gem := range tpInst.UpstreamQueueAttributeList {
809 gemPortIDs = append(gemPortIDs, gem.GemportID)
810 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700811 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700812
813 if tpInstanceExists {
814 return allocID, gemPortIDs, techProfileInstance
815 }
816
817 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700818 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700819 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000820 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700821 log.Fields{
822 "alloc-ids": allocIDs,
823 "gemports": allgemPortIDs,
824 "device-id": f.deviceHandler.device.Id})
825 // Send Tconts and GEM ports to KV store
826 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
827 return allocID, gemPortIDs, techProfileInstance
828 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000829 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700830 log.Fields{
831 "tpInst": tpInst})
832 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530833 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530834}
835
npujarec5762e2020-01-01 14:08:48 +0530836func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530837
Neha Sharma96b7bf22020-06-15 10:37:32 +0000838 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530839 log.Fields{
840 "intf-id": intfID,
841 "onu-id": onuID,
842 "uni-id": uniID,
843 "alloc-id": allocID,
844 "gemport-ids": gemPortIDs,
845 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530846 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530847 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000848 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 +0530849 }
npujarec5762e2020-01-01 14:08:48 +0530850 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000851 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 +0530852 }
npujarec5762e2020-01-01 14:08:48 +0530853 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000854 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 +0530855 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000856 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 -0400857 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530858 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400859 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530860}
861
Neha Sharma96b7bf22020-06-15 10:37:32 +0000862func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000863 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530864 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000865 for _, intfID := range techRange.IntfIds {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700866 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[intfID].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400867 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000868 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530869 log.Fields{
870 "intf-id": intfID,
871 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530872 }
873 }
874 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400875 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530876 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530877 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800878 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530879 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
880 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530881 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000882 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530883 log.Fields{
884 "numofTech": tpCount,
885 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
886 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530887 return nil
888}
889
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700890func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530891 portNo uint32, uplinkClassifier map[string]interface{},
892 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700893 allocID uint32, gemportID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700894 uplinkClassifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000895 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530896 log.Fields{
897 "uplinkClassifier": uplinkClassifier,
898 "uplinkAction": uplinkAction})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700899 return f.addSymmetricDataPathFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
900 Upstream, logicalFlow, allocID, gemportID, tpID, pbitToGem)
Manikkaraj k884c1242019-04-11 16:26:42 +0530901 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530902}
903
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700904func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530905 portNo uint32, downlinkClassifier map[string]interface{},
906 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700907 allocID uint32, gemportID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700908 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000909 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530910 log.Fields{
911 "downlinkClassifier": downlinkClassifier,
912 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400913 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
914 if vlan, exists := downlinkClassifier[VlanVid]; exists {
915 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700916 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Neha Sharma96b7bf22020-06-15 10:37:32 +0000917 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, intfID, onuID, uniID) {
918 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530919 log.Fields{
920 "flow": logicalFlow,
921 "device-id": f.deviceHandler.device.Id,
922 "onu-id": onuID,
923 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800924 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400925 }
926 }
927 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530928 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400929
Manikkaraj k884c1242019-04-11 16:26:42 +0530930 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700931 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400932 // vlan_vid is a uint32. must be type asserted as such or conversion fails
933 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530934 if ok {
935 downlinkAction[VlanVid] = dlClVid & 0xfff
936 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530937 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530938 "reason": "failed-to-convert-vlanid-classifier",
939 "vlan-id": VlanVid,
940 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530941 }
942
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700943 return f.addSymmetricDataPathFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
944 Downstream, logicalFlow, allocID, gemportID, tpID, pbitToGem)
manikkaraj kbf256be2019-03-25 00:13:48 +0530945}
946
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700947func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530948 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700949 allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
950
951 var inverseDirection string
952 if direction == Upstream {
953 inverseDirection = Downstream
954 } else {
955 inverseDirection = Upstream
956 }
957
Neha Sharma96b7bf22020-06-15 10:37:32 +0000958 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530959 log.Fields{
960 "intf-id": intfID,
961 "onu-id": onuID,
962 "uni-id": uniID,
963 "device-id": f.deviceHandler.device.Id,
964 "classifier": classifier,
965 "action": action,
966 "direction": direction,
967 "alloc-id": allocID,
968 "gemport-id": gemPortID,
969 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700970
971 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000972 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +0530973 log.Fields{
974 "device-id": f.deviceHandler.device.Id,
975 "intf-id": intfID,
976 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800977 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530978 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800979 classifierProto, err := makeOpenOltClassifierField(classifier)
980 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530981 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530982 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000983 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530984 log.Fields{
985 "classifier": *classifierProto,
986 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000987 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800988 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530989 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530990 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000991 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530992 log.Fields{
993 "action": *actionProto,
994 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +0000995 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530996 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530997 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800998 log.Fields{
999 "classifier": classifier,
1000 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301001 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001002 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301003 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001004
1005 // Get symmetric flowID if it exists
1006 // This symmetric flowID will be needed by agent software to use the same device flow-id that was used for the
1007 // symmetric flow earlier
1008 // symmetric flowID 0 is considered by agent as non-existent symmetric flow
1009 keySymm := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: inverseDirection, tpID: tpID}
1010 f.subscriberDataPathFlowIDMapLock.RLock()
1011 symmFlowID := f.subscriberDataPathFlowIDMap[keySymm]
1012 f.subscriberDataPathFlowIDMapLock.RUnlock()
1013
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001014 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001015 OnuId: int32(onuID),
1016 UniId: int32(uniID),
1017 FlowId: logicalFlow.Id,
1018 FlowType: direction,
1019 AllocId: int32(allocID),
1020 NetworkIntfId: int32(networkIntfID),
1021 GemportId: int32(gemPortID),
1022 Classifier: classifierProto,
1023 Action: actionProto,
1024 Priority: int32(logicalFlow.Priority),
1025 Cookie: logicalFlow.Cookie,
1026 PortNo: portNo,
1027 TechProfileId: tpID,
1028 ReplicateFlow: len(pbitToGem) > 0,
1029 PbitToGemport: pbitToGem,
1030 SymmetricFlowId: symmFlowID,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001031 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001032 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001033 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301034 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001035 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301036 log.Fields{"direction": direction,
1037 "device-id": f.deviceHandler.device.Id,
1038 "flow": flow,
1039 "intf-id": intfID,
1040 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001041 flowInfo := rsrcMgr.FlowInfo{Flow: &flow, IsSymmtricFlow: true}
1042 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(flow.AccessIntfId), flow.OnuId, flow.UniId, flow.FlowId, flowInfo); err != nil {
1043 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301044 log.Fields{
1045 "flow": flow,
1046 "device-id": f.deviceHandler.device.Id,
1047 "intf-id": intfID,
1048 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001049 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001050
1051 // Update the current flowID to the map
1052 keyCurr := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: direction, tpID: tpID}
1053 f.subscriberDataPathFlowIDMapLock.Lock()
1054 f.subscriberDataPathFlowIDMap[keyCurr] = logicalFlow.Id
1055 f.subscriberDataPathFlowIDMapLock.Unlock()
1056
David K. Bainbridge794735f2020-02-11 21:01:37 -08001057 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301058}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001059
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001060func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1061 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001062 gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301063
Neha Sharma96b7bf22020-06-15 10:37:32 +00001064 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301065 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301066 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001067 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301068 "action": action,
1069 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001070 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301071 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301072
1073 // Clear the action map
1074 for k := range action {
1075 delete(action, k)
1076 }
1077
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001078 action[TrapToHost] = true
1079 classifier[UDPSrc] = uint32(68)
1080 classifier[UDPDst] = uint32(67)
1081 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301082
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001083 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001084 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301085 log.Fields{
1086 "device-id": f.deviceHandler.device.Id,
1087 "intf-id": intfID,
1088 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001089 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301090 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301091
Neha Sharma96b7bf22020-06-15 10:37:32 +00001092 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301093 log.Fields{
1094 "ul_classifier": classifier,
1095 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001096 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301097 "intf-id": intfID,
1098 "onu-id": onuID,
1099 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301100
David K. Bainbridge794735f2020-02-11 21:01:37 -08001101 classifierProto, err := makeOpenOltClassifierField(classifier)
1102 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301103 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301104 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001105 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001106 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001107 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301108 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301109 }
1110
David K. Bainbridge794735f2020-02-11 21:01:37 -08001111 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001112 OnuId: int32(onuID),
1113 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001114 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001115 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001116 AllocId: int32(allocID),
1117 NetworkIntfId: int32(networkIntfID),
1118 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301119 Classifier: classifierProto,
1120 Action: actionProto,
1121 Priority: int32(logicalFlow.Priority),
1122 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001123 PortNo: portNo,
1124 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001125 ReplicateFlow: len(pbitToGem) > 0,
1126 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001127 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001128 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001129 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001130 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001131 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301132 log.Fields{
1133 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001134 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301135 "intf-id": intfID,
1136 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001137 flowInfo := rsrcMgr.FlowInfo{Flow: &dhcpFlow}
1138 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(dhcpFlow.AccessIntfId), dhcpFlow.OnuId, dhcpFlow.UniId, dhcpFlow.FlowId, flowInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301139 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1140 log.Fields{
1141 "flow": dhcpFlow,
1142 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301143 }
1144
David K. Bainbridge794735f2020-02-11 21:01:37 -08001145 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301146}
1147
Esin Karamanae41e2b2019-12-17 18:13:13 +00001148//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301149func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001150 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
1151 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, tpID, pbitToGem)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001152}
1153
1154//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301155func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001156 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001157
Neha Sharma96b7bf22020-06-15 10:37:32 +00001158 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001159 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301160 return olterrors.NewErrNotFound("nni-interface-id",
1161 log.Fields{
1162 "classifier": classifier,
1163 "action": action,
1164 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001165 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001166 }
1167
1168 // Clear the action map
1169 for k := range action {
1170 delete(action, k)
1171 }
1172
1173 action[TrapToHost] = true
1174 classifier[PacketTagType] = SingleTag
1175 delete(classifier, VlanVid)
1176
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001177 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001178 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001179 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001180 }
1181
Neha Sharma96b7bf22020-06-15 10:37:32 +00001182 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301183 log.Fields{
1184 "ul_classifier": classifier,
1185 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001186 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301187 "device-id": f.deviceHandler.device.Id,
1188 "intf-id": intfID,
1189 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001190
David K. Bainbridge794735f2020-02-11 21:01:37 -08001191 classifierProto, err := makeOpenOltClassifierField(classifier)
1192 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301193 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001194 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001195 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301196 log.Fields{
1197 "classifier": *classifierProto,
1198 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001199 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001200 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301201 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001202 }
1203
David K. Bainbridge794735f2020-02-11 21:01:37 -08001204 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001205 OnuId: int32(onuID),
1206 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001207 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001208 FlowType: Upstream,
1209 AllocId: int32(allocID),
1210 NetworkIntfId: int32(networkIntfID),
1211 GemportId: int32(gemPortID),
1212 Classifier: classifierProto,
1213 Action: actionProto,
1214 Priority: int32(logicalFlow.Priority),
1215 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001216 PortNo: portNo,
1217 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001218 ReplicateFlow: len(pbitToGem) > 0,
1219 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001220 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001221
David K. Bainbridge794735f2020-02-11 21:01:37 -08001222 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001223 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001224 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001225
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001226 flowInfo := rsrcMgr.FlowInfo{Flow: &flow}
1227 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(flow.AccessIntfId), flow.OnuId, flow.UniId, flow.FlowId, flowInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301228 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 +00001229 }
1230
David K. Bainbridge794735f2020-02-11 21:01:37 -08001231 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001232}
1233
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001234// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001235func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1236 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001237 gemPortID uint32, vlanID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001238 logger.Infow(ctx, "adding-eapol-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301239 log.Fields{
1240 "intf-id": intfID,
1241 "onu-id": onuID,
1242 "port-no": portNo,
1243 "alloc-id": allocID,
1244 "gemport-id": gemPortID,
1245 "vlan-id": vlanID,
1246 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301247
1248 uplinkClassifier := make(map[string]interface{})
1249 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301250
manikkaraj kbf256be2019-03-25 00:13:48 +05301251 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001252 uplinkClassifier[EthType] = uint32(EapEthType)
1253 uplinkClassifier[PacketTagType] = SingleTag
1254 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001255 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301256 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001257 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001258 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001259 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301260 "device-id": f.deviceHandler.device.Id,
1261 "onu-id": onuID,
1262 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001263 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301264 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301265 //Add Uplink EAPOL Flow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001266 logger.Debugw(ctx, "creating-ul-eapol-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301267 log.Fields{
1268 "ul_classifier": uplinkClassifier,
1269 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001270 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301271 "device-id": f.deviceHandler.device.Id,
1272 "intf-id": intfID,
1273 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301274
David K. Bainbridge794735f2020-02-11 21:01:37 -08001275 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1276 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301277 return olterrors.NewErrInvalidValue(log.Fields{
1278 "classifier": uplinkClassifier,
1279 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301280 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001281 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301282 log.Fields{
1283 "classifier": *classifierProto,
1284 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001285 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001286 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301287 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301288 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001289 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301290 log.Fields{
1291 "action": *actionProto,
1292 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001293 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301294 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301295 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001296 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301297 "action": action,
1298 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001299 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301300 }
1301
David K. Bainbridge794735f2020-02-11 21:01:37 -08001302 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001303 OnuId: int32(onuID),
1304 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001305 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001306 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001307 AllocId: int32(allocID),
1308 NetworkIntfId: int32(networkIntfID),
1309 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301310 Classifier: classifierProto,
1311 Action: actionProto,
1312 Priority: int32(logicalFlow.Priority),
1313 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001314 PortNo: portNo,
1315 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001316 ReplicateFlow: len(pbitToGem) > 0,
1317 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001318 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001319 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001320 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001321 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001322 logger.Infow(ctx, "eapol-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301323 log.Fields{
1324 "device-id": f.deviceHandler.device.Id,
1325 "onu-id": onuID,
1326 "intf-id": intfID,
1327 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001328 flowInfo := rsrcMgr.FlowInfo{Flow: &upstreamFlow}
1329 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(upstreamFlow.AccessIntfId), upstreamFlow.OnuId, upstreamFlow.UniId, upstreamFlow.FlowId, flowInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301330 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1331 log.Fields{
1332 "flow": upstreamFlow,
1333 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301334 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001335 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301336}
1337
David K. Bainbridge794735f2020-02-11 21:01:37 -08001338func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001339 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001340
1341 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1342 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1343 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001344 if vlanID != ReservedVlan {
1345 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001346 classifier.OVid = vid
1347 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301348 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001349 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1350 vid := uint32(metadata)
1351 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001352 classifier.IVid = vid
1353 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301354 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301355 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001356 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301357 classifier.OPbits = vlanPcp
1358 } else {
1359 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301360 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001361 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1362 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1363 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1364 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001365 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001366 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1367 classifier.PktTagType = pktTagType
1368
1369 switch pktTagType {
1370 case SingleTag:
1371 case DoubleTag:
1372 case Untagged:
1373 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001374 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301375 }
1376 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001377 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301378}
1379
Gamze Abaka724d0852020-03-18 12:10:24 +00001380func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001381 var actionCmd openoltpb2.ActionCmd
1382 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301383 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001384 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301385 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001386 if _, ok := actionInfo[VlanPcp]; ok {
1387 action.Cmd.RemarkInnerPbits = true
1388 action.IPbits = actionInfo[VlanPcp].(uint32)
1389 if _, ok := actionInfo[VlanVid]; ok {
1390 action.Cmd.TranslateInnerTag = true
1391 action.IVid = actionInfo[VlanVid].(uint32)
1392 }
1393 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001394 } else if _, ok := actionInfo[PushVlan]; ok {
1395 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301396 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001397 if _, ok := actionInfo[VlanPcp]; ok {
1398 action.OPbits = actionInfo[VlanPcp].(uint32)
1399 action.Cmd.RemarkOuterPbits = true
1400 if _, ok := classifierInfo[VlanVid]; ok {
1401 action.IVid = classifierInfo[VlanVid].(uint32)
1402 action.Cmd.TranslateInnerTag = true
1403 }
1404 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001405 } else if _, ok := actionInfo[TrapToHost]; ok {
1406 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301407 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001408 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301409 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001410 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301411}
1412
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001413// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001414func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1415 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301416}
1417
Gamze Abakafee36392019-10-03 11:17:24 +00001418// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001419func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301420 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001421 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1422
Gamze Abakafee36392019-10-03 11:17:24 +00001423 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301424 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001425 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301426 // return err
1427 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001428 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001429 logger.Debugw(ctx, "tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001430 }
1431 return nil
1432}
1433
1434// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301435func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001436 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001437 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001438 }
npujarec5762e2020-01-01 14:08:48 +05301439 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301440 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1441 log.Fields{
1442 "tp-id": tpID,
1443 "uni-port-name": uniPortName,
1444 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001445 }
1446 return nil
1447}
1448
David K. Bainbridge794735f2020-02-11 21:01:37 -08001449func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001450
1451 var intfID uint32
1452 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1453 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1454 */
1455 if deviceFlow.AccessIntfId != -1 {
1456 intfID = uint32(deviceFlow.AccessIntfId)
1457 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001458 // We need to log the valid interface ID.
1459 // For trap-on-nni flows, the access_intf_id is invalid (-1), so choose the network_intf_id.
Daniele Rossi22db98e2019-07-11 11:50:00 +00001460 intfID = uint32(deviceFlow.NetworkIntfId)
1461 }
1462
Neha Sharma96b7bf22020-06-15 10:37:32 +00001463 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301464 "flow": *deviceFlow,
1465 "device-id": f.deviceHandler.device.Id,
1466 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001467 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001468
1469 st, _ := status.FromError(err)
1470 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001471 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001472 "err": err,
1473 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301474 "device-id": f.deviceHandler.device.Id,
1475 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001476 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301477 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001478
1479 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001480 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301481 log.Fields{"err": err,
1482 "device-flow": deviceFlow,
1483 "device-id": f.deviceHandler.device.Id,
1484 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001485 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001486 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001487 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301488 log.Fields{
1489 "flow": *deviceFlow,
1490 "device-id": f.deviceHandler.device.Id,
1491 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001492
1493 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1494 if deviceFlow.AccessIntfId != -1 {
1495 // No need to register the flow if it is a trap on nni flow.
1496 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1497 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1498 return err
1499 }
1500 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001501 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001502}
1503
Neha Sharma96b7bf22020-06-15 10:37:32 +00001504func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1505 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301506 log.Fields{
1507 "flow": *deviceFlow,
1508 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001509 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001510 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001511 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001512 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301513 log.Fields{
1514 "err": err,
1515 "deviceFlow": deviceFlow,
1516 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001517 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001518 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001519 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001520 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001521
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001522 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001523 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001524 "of-flow-id": ofFlowID,
1525 "flow": *deviceFlow,
1526 "device-id": f.deviceHandler.device.Id,
1527 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001528 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301529}
1530
David K. Bainbridge794735f2020-02-11 21:01:37 -08001531func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001532
1533 classifierInfo := make(map[string]interface{})
1534 actionInfo := make(map[string]interface{})
1535
1536 classifierInfo[EthType] = uint32(LldpEthType)
1537 classifierInfo[PacketTagType] = Untagged
1538 actionInfo[TrapToHost] = true
1539
1540 // LLDP flow is installed to trap LLDP packets on the NNI port.
1541 // We manage flow_id resource pool on per PON port basis.
1542 // Since this situation is tricky, as a hack, we pass the NNI port
1543 // index (network_intf_id) as PON port Index for the flow_id resource
1544 // pool. Also, there is no ONU Id available for trapping LLDP packets
1545 // on NNI port, use onu_id as -1 (invalid)
1546 // ****************** CAVEAT *******************
1547 // This logic works if the NNI Port Id falls within the same valid
1548 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1549 // we need to have a re-look at this.
1550 // *********************************************
1551
1552 var onuID = -1
1553 var uniID = -1
1554 var gemPortID = -1
1555
Neha Sharma96b7bf22020-06-15 10:37:32 +00001556 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001557 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301558 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001559 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001560 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001561 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001562 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001563 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001564
David K. Bainbridge794735f2020-02-11 21:01:37 -08001565 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1566 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301567 return olterrors.NewErrInvalidValue(
1568 log.Fields{
1569 "classifier": classifierInfo,
1570 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001571 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001572 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301573 log.Fields{
1574 "classifier": *classifierProto,
1575 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001576 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001577 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301578 return olterrors.NewErrInvalidValue(
1579 log.Fields{
1580 "action": actionInfo,
1581 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001582 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001583 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301584 log.Fields{
1585 "action": *actionProto,
1586 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001587
1588 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1589 OnuId: int32(onuID), // OnuId not required
1590 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001591 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001592 FlowType: Downstream,
1593 NetworkIntfId: int32(networkInterfaceID),
1594 GemportId: int32(gemPortID),
1595 Classifier: classifierProto,
1596 Action: actionProto,
1597 Priority: int32(flow.Priority),
1598 Cookie: flow.Cookie,
1599 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001600 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001601 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301602 log.Fields{
1603 "flow": downstreamflow,
1604 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001605 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001606 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301607 log.Fields{
1608 "device-id": f.deviceHandler.device.Id,
1609 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001610 "flow-id": flow.Id})
1611 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
1612 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
1613 return olterrors.NewErrPersistence("update", "flow", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301614 log.Fields{
1615 "flow": downstreamflow,
1616 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001617 }
1618 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301619}
1620
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001621func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1622 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001623}
1624
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001625//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001626func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001627 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1628 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1629 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001630 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301631 log.Fields{
1632 "intf-id": intfID,
1633 "onu-id": onuID,
1634 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001635 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001636 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301637 return nil, olterrors.NewErrNotFound("onu-child-device",
1638 log.Fields{
1639 "onu-id": onuID,
1640 "intf-id": intfID,
1641 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001642 }
1643 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1644 //better to ad the device to cache here.
1645 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1646 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001647 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301648 log.Fields{
1649 "intf-id": intfID,
1650 "onu-id": onuID,
1651 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001652 }
1653
1654 return onuDev.(*OnuDevice), nil
1655}
1656
1657//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001658func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1659 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301660 log.Fields{
1661 "pon-port": intfID,
1662 "onu-id": onuID,
1663 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001664 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001665 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001666 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301667 return nil, olterrors.NewErrNotFound("onu",
1668 log.Fields{
1669 "interface-id": parentPortNo,
1670 "onu-id": onuID,
1671 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001672 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301673 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001674 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301675 log.Fields{
1676 "device-id": f.deviceHandler.device.Id,
1677 "child_device_id": onuDevice.Id,
1678 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301679 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301680}
1681
Neha Sharma96b7bf22020-06-15 10:37:32 +00001682func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1683 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301684 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001685 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301686 log.Fields{
1687 "intf-id": intfID,
1688 "onu-id": onuID,
1689 "uni-id": uniID,
1690 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001691 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301692 }
1693
1694 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001695 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301696 log.Fields{
1697 "msg": *delGemPortMsg,
1698 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001699 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301700 delGemPortMsg,
1701 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301702 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001703 onuDev.deviceType,
1704 onuDev.deviceID,
1705 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301706 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1707 log.Fields{
1708 "from-adapter": f.deviceHandler.device.Type,
1709 "to-adapter": onuDev.deviceType,
1710 "onu-id": onuDev.deviceID,
1711 "proxyDeviceID": onuDev.proxyDeviceID,
1712 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301713 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001714 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301715 log.Fields{
1716 "msg": delGemPortMsg,
1717 "from-adapter": f.deviceHandler.device.Type,
1718 "to-adapter": onuDev.deviceType,
1719 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301720 return nil
1721}
1722
Neha Sharma96b7bf22020-06-15 10:37:32 +00001723func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1724 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301725 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001726 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301727 log.Fields{
1728 "intf-id": intfID,
1729 "onu-id": onuID,
1730 "uni-id": uniID,
1731 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001732 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301733 }
1734
1735 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001736 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301737 log.Fields{
1738 "msg": *delTcontMsg,
1739 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001740 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301741 delTcontMsg,
1742 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301743 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001744 onuDev.deviceType,
1745 onuDev.deviceID,
1746 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301747 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1748 log.Fields{
1749 "from-adapter": f.deviceHandler.device.Type,
1750 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1751 "proxyDeviceID": onuDev.proxyDeviceID,
1752 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301753 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001754 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301755 log.Fields{
1756 "msg": delTcontMsg,
1757 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301758 return nil
1759}
1760
Girish Gowdrac3037402020-01-22 20:29:53 +05301761// Once the gemport is released for a given onu, it also has to be cleared from local cache
1762// which was used for deriving the gemport->logicalPortNo during packet-in.
1763// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1764// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001765func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001766
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001767 f.onuGemInfoLock.Lock()
1768 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001769
Neha Sharma96b7bf22020-06-15 10:37:32 +00001770 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301771 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001772 "gem-port-id": gemPortID,
1773 "intf-id": intfID,
1774 "onu-id": onuID,
1775 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001776 "onu-gem": f.onuGemInfo})
Girish Gowdra9602eb42020-09-09 15:50:39 -07001777
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001778 onugem := f.onuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001779deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001780 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301781 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001782 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301783 // If the gemport is found, delete it from local cache.
1784 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001785 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1786 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001787 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301788 log.Fields{
1789 "intf-id": intfID,
1790 "onu-id": onuID,
1791 "deletedgemport-id": gemPortID,
1792 "gemports": onu.GemPorts,
1793 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001794 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301795 }
1796 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001797 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301798 }
1799 }
1800}
1801
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301802//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001803// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301804func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001805 gemPortID int32, flowID uint64, portNum uint32) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001806
Neha Sharma96b7bf22020-06-15 10:37:32 +00001807 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001808 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301809 return olterrors.NewErrNotFound("tp-id",
1810 log.Fields{
1811 "flow": flow,
1812 "intf": Intf,
1813 "onu-id": onuID,
1814 "uni-id": uniID,
1815 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001816 }
Gamze Abakafee36392019-10-03 11:17:24 +00001817
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001818 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
1819 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
1820 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1821 log.Fields{
1822 "tpPath": tpPath,
1823 "device-id": f.deviceHandler.device.Id})
1824 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
1825 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1826 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1827 log.Fields{
1828 "tp-id": tpID,
1829 "path": tpPath}, err)
1830 }
1831
1832 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1833
1834 if used {
1835 f.flowsUsedByGemPortKey.Lock()
1836 defer f.flowsUsedByGemPortKey.Unlock()
1837
1838 flowIDs := f.flowsUsedByGemPort[uint32(gemPortID)]
1839 for i, flowIDinMap := range flowIDs {
1840 if flowIDinMap == flowID {
1841 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1842 // everytime flowsUsedByGemPort cache is updated the same should be updated
1843 // in kv store by calling UpdateFlowIDsForGem
1844 f.flowsUsedByGemPort[uint32(gemPortID)] = flowIDs
1845 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs); err != nil {
1846 return err
1847 }
1848 break
1849 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001850 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001851 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1852 log.Fields{
1853 "gemport-id": gemPortID,
1854 "usedByFlows": flowIDs,
1855 "device-id": f.deviceHandler.device.Id})
1856 return nil
1857 }
1858 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
1859 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1860 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1861 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
1862 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
1863 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
1864 f.onuIdsLock.Lock() // TODO: What is this lock?
1865
1866 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1867 // by calling DeleteFlowIDsForGem
1868 f.flowsUsedByGemPortKey.Lock()
1869 delete(f.flowsUsedByGemPort, uint32(gemPortID))
1870 f.flowsUsedByGemPortKey.Unlock()
1871 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1872 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1873
1874 f.onuIdsLock.Unlock()
1875
1876 // Delete the gem port on the ONU.
1877 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1878 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1879 log.Fields{
1880 "err": err,
1881 "intf": Intf,
1882 "onu-id": onuID,
1883 "uni-id": uniID,
1884 "device-id": f.deviceHandler.device.Id,
1885 "gemport-id": gemPortID})
1886 }
1887 switch techprofileInst := techprofileInst.(type) {
1888 case *tp.TechProfile:
1889 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
1890 if !ok {
1891 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
1892 logger.Warn(ctx, err)
1893 }
1894 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1895 logger.Warn(ctx, err)
1896 }
1897 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 {
1898 logger.Warn(ctx, err)
1899 }
1900 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 {
1901 logger.Warn(ctx, err)
1902 }
1903 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
1904 // Delete the TCONT on the ONU.
1905 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID, tpPath); err != nil {
1906 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
1907 log.Fields{
1908 "intf": Intf,
1909 "onu-id": onuID,
1910 "uni-id": uniID,
1911 "device-id": f.deviceHandler.device.Id,
1912 "alloc-id": techprofileInst.UsScheduler.AllocID})
1913 }
1914 }
1915 case *tp.EponProfile:
1916 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
1917 logger.Warn(ctx, err)
1918 }
1919 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1920 logger.Warn(ctx, err)
1921 }
1922 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
1923 // Delete the TCONT on the ONU.
1924 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID, tpPath); err != nil {
1925 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301926 log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001927 "intf": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05301928 "onu-id": onuID,
1929 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001930 "device-id": f.deviceHandler.device.Id,
1931 "alloc-id": techprofileInst.AllocID})
Gamze Abakafee36392019-10-03 11:17:24 +00001932 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001933 default:
1934 logger.Errorw(ctx, "error-unknown-tech",
1935 log.Fields{
1936 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001937 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001938
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301939 return nil
1940}
1941
David K. Bainbridge794735f2020-02-11 21:01:37 -08001942// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07001943func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001944 var flowInfo *rsrcMgr.FlowInfo
Neha Sharma96b7bf22020-06-15 10:37:32 +00001945 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05301946 log.Fields{
1947 "flowDirection": flowDirection,
1948 "flow": *flow,
1949 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001950
1951 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001952 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001953 }
1954
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301955 classifierInfo := make(map[string]interface{})
1956
Neha Sharma96b7bf22020-06-15 10:37:32 +00001957 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301958 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001959 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001960 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301961 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301962
David K. Bainbridge794735f2020-02-11 21:01:37 -08001963 onuID := int32(onu)
1964 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301965
1966 for _, field := range flows.GetOfbFields(flow) {
1967 if field.Type == flows.IP_PROTO {
1968 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001969 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301970 }
1971 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001972 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05301973 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001974 "flow-id": flow.Id,
1975 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05301976 "onu-id": onuID,
1977 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301978
1979 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1980 onuID = -1
1981 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00001982 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
1983 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001984 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001985 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001986 log.Fields{
1987 "port-number": inPort,
1988 "error": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001989 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08001990 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301991 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001992 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); flowInfo == nil {
1993 logger.Errorw(ctx, "flow-info-not-found-for-flow-to-be-removed", log.Fields{"flow-id": flow.Id, "intf-id": Intf, "onu-id": onuID, "uni-id": uniID})
1994 return olterrors.NewErrPersistence("remove", "flow", flow.Id, log.Fields{"flow": flow}, err)
1995 }
1996 removeFlowMessage := openoltpb2.Flow{FlowId: flowInfo.Flow.FlowId, FlowType: flowInfo.Flow.FlowType}
1997 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flowInfo.Flow})
1998 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
1999 return err
2000 }
2001 if err = f.resourceMgr.RemoveFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); err != nil {
2002 logger.Errorw(ctx, "failed-to-remove-flow-on-kv-store", log.Fields{"error": err})
2003 return err
2004 }
2005 if !flowInfo.Flow.ReplicateFlow {
2006 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, flowInfo.Flow.GemportId, flowInfo.Flow.FlowId, portNum); err != nil {
2007 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2008 "flow-id": flow.Id,
2009 "stored-flow": flowInfo.Flow,
2010 "device-id": f.deviceHandler.device.Id,
2011 "stored-flow-id": flowInfo.Flow.FlowId,
2012 "onu-id": onuID,
2013 "intf": Intf,
2014 })
2015 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302016 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002017 } else {
2018 gems := make([]uint32, 0)
2019 for _, gem := range flowInfo.Flow.PbitToGemport {
2020 gems = appendUnique32bit(gems, gem)
2021 }
2022 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": gems})
2023 for _, gem := range gems {
2024 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, int32(gem), flowInfo.Flow.FlowId, portNum); err != nil {
2025 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002026 "flow-id": flow.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002027 "stored-flow": flowInfo.Flow,
Matteo Scandolo92186242020-06-12 10:54:18 -07002028 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002029 "stored-flow-id": flowInfo.Flow.FlowId,
Matteo Scandolo92186242020-06-12 10:54:18 -07002030 "onu-id": onuID,
2031 "intf": Intf,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002032 "gem": gem,
Matteo Scandolo92186242020-06-12 10:54:18 -07002033 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002034 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302035 }
2036 }
2037 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002038
2039 // If datapath flow, clear the symmetric flow data from the subscriberDataPathFlowIDMap map
2040 if isDatapathFlow(flow) {
2041 if tpID, err := getTpIDFromFlow(ctx, flow); err != nil {
2042 var inverseDirection string
2043 if flowDirection == Upstream {
2044 inverseDirection = Downstream
2045 } else {
2046 inverseDirection = Upstream
2047 }
2048
2049 keySymm := subscriberDataPathFlowIDKey{intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), direction: inverseDirection, tpID: tpID}
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002050 f.subscriberDataPathFlowIDMapLock.Lock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002051 delete(f.subscriberDataPathFlowIDMap, keySymm)
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002052 f.subscriberDataPathFlowIDMapLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002053 }
2054 }
2055 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002056}
2057
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002058//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002059func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002060
2061 f.incrementActiveFlowRemoveCount(ctx, flow)
2062 defer f.decrementActiveFlowRemoveCount(ctx, flow)
2063
Neha Sharma96b7bf22020-06-15 10:37:32 +00002064 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302065 var direction string
2066 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002067
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302068 for _, action := range flows.GetActions(flow) {
2069 if action.Type == flows.OUTPUT {
2070 if out := action.GetOutput(); out != nil {
2071 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002072 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302073 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002074 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002075 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002076 }
2077 }
2078 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002079
2080 if flows.HasGroup(flow) {
2081 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002082 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002083 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302084 direction = Upstream
2085 } else {
2086 direction = Downstream
2087 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302088
Neha Sharma96b7bf22020-06-15 10:37:32 +00002089 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002090 if err != nil {
2091 return err
2092 }
2093
2094 userKey := tpLockKey{intfID, onuID, uniID}
2095
2096 // Serialize flow removes on a per subscriber basis
2097 if f.perUserFlowHandleLock.TryLock(userKey) {
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002098 err = f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002099 f.perUserFlowHandleLock.Unlock(userKey)
2100 } else {
2101 // Ideally this should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00002102 logger.Errorw(ctx, "failed-to-acquire-lock-to-remove-flow--remove-aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07002103 return errors.New("failed-to-acquire-per-user-lock")
2104 }
2105
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002106 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002107}
2108
Esin Karamanae41e2b2019-12-17 18:13:13 +00002109//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2110func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2111 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2112 if ethType, ok := classifierInfo[EthType]; ok {
2113 if ethType.(uint32) == IPv4EthType {
2114 if ipProto, ok := classifierInfo[IPProto]; ok {
2115 if ipProto.(uint32) == IgmpProto {
2116 return true
2117 }
2118 }
2119 }
2120 }
2121 }
2122 return false
2123}
2124
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002125// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302126// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002127func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002128 classifierInfo := make(map[string]interface{})
2129 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002130 var UsMeterID uint32
2131 var DsMeterID uint32
2132
Neha Sharma96b7bf22020-06-15 10:37:32 +00002133 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302134 log.Fields{
2135 "flow": flow,
2136 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002137 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002138
Neha Sharma96b7bf22020-06-15 10:37:32 +00002139 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002140 if err != nil {
2141 // Error logging is already done in the called function
2142 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002143 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302144 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002145
Esin Karamanccb714b2019-11-29 15:02:06 +00002146 if flows.HasGroup(flow) {
2147 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002148 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002149 }
2150
manikkaraj k17652a72019-05-06 09:06:36 -04002151 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002152 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002153 if err != nil {
2154 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002155 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002156 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002157
Neha Sharma96b7bf22020-06-15 10:37:32 +00002158 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302159 log.Fields{
2160 "classifierinfo_inport": classifierInfo[InPort],
2161 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002162 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002163
Humera Kouser94d7a842019-08-25 19:04:32 -04002164 if ethType, ok := classifierInfo[EthType]; ok {
2165 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002166 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002167 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002168 }
2169 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002170 if ipProto, ok := classifierInfo[IPProto]; ok {
2171 if ipProto.(uint32) == IPProtoDhcp {
2172 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302173 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002174 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002175 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002176 }
2177 }
2178 }
2179 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002180 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002181 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002182 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002183 }
A R Karthick1f85b802019-10-11 05:06:05 +00002184
Girish Gowdra9602eb42020-09-09 15:50:39 -07002185 // If we are here it is not a trap-from-nni flow, i.e., it is subscriber specific flow.
2186 // Wait for any FlowRemoves for that specific subscriber to finish first
2187 // The goal here is to serialize FlowRemove and FlowAdd. FlowRemove take priority
2188 f.waitForFlowRemoveToFinish(ctx, flow)
2189
npujarec5762e2020-01-01 14:08:48 +05302190 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002191
Neha Sharma96b7bf22020-06-15 10:37:32 +00002192 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002193 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302194 return olterrors.NewErrNotFound("tpid-for-flow",
2195 log.Fields{
2196 "flow": flow,
2197 "intf-id": IntfID,
2198 "onu-id": onuID,
2199 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002200 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002201 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302202 log.Fields{
2203 "tp-id": TpID,
2204 "intf-id": intfID,
2205 "onu-id": onuID,
2206 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002207 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002208 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002209 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002210 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002211 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002212 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002213
2214 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002215 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002216}
Girish Gowdra3d633032019-12-10 16:37:05 +05302217
Girish Gowdra9602eb42020-09-09 15:50:39 -07002218//WaitForFlowRemoveToFinishForSubscriber blocks until flow removes are complete for a given subscriber
2219func (f *OpenOltFlowMgr) WaitForFlowRemoveToFinishForSubscriber(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) {
2220 var flowRemoveData pendingFlowRemoveData
2221 var ok bool
2222
2223 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
2224 logger.Debugw(ctx, "wait-for-flow-remove-to-finish-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
2225
2226 f.pendingFlowRemoveDataPerSubscriberLock.RLock()
2227 if flowRemoveData, ok = f.pendingFlowRemoveDataPerSubscriber[key]; !ok {
2228 logger.Debugw(ctx, "no-pending-flow-to-remove", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
2229 f.pendingFlowRemoveDataPerSubscriberLock.RUnlock()
2230 return
Girish Gowdra3d633032019-12-10 16:37:05 +05302231 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002232 f.pendingFlowRemoveDataPerSubscriberLock.RUnlock()
2233
2234 // Wait for all flow removes to finish first
2235 <-flowRemoveData.allFlowsRemoved
2236
2237 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 -07002238}
2239
Esin Karamanccb714b2019-11-29 15:02:06 +00002240// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002241func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002242 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002243 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302244 "classifier-info": classifierInfo,
2245 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002246
Esin Karaman65409d82020-03-18 10:58:18 +00002247 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002248 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002249 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002250 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002251
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002252 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002253
David K. Bainbridge794735f2020-02-11 21:01:37 -08002254 onuID := NoneOnuID
2255 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002256
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002257 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002258 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002259 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002260 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002261 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2262 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002263 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002264 }
2265 groupID := actionInfo[GroupID].(uint32)
2266 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002267 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002268 FlowType: Multicast,
2269 NetworkIntfId: int32(networkInterfaceID),
2270 GroupId: groupID,
2271 Classifier: classifierProto,
2272 Priority: int32(flow.Priority),
2273 Cookie: flow.Cookie}
2274
Kent Hagermane6ff1012020-07-14 15:07:53 -04002275 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002276 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002277 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002278 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002279 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002280 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002281 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002282 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002283 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002284 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002285 //cached group can be removed now
2286 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2287 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2288 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002289 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002290
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002291 flowInfo := rsrcMgr.FlowInfo{Flow: &multicastFlow}
2292 if err = f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
2293 return olterrors.NewErrPersistence("update", "flow", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002294 }
2295 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002296}
2297
Esin Karaman65409d82020-03-18 10:58:18 +00002298//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2299func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2300 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002301 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002302 if err != nil {
2303 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2304 }
2305 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002306 }
Esin Karaman65409d82020-03-18 10:58:18 +00002307 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302308 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002309 if e == nil && len(nniPorts) > 0 {
2310 return nniPorts[0], nil
2311 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302312 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002313}
2314
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002315//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002316func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002317
Neha Sharma96b7bf22020-06-15 10:37:32 +00002318 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302319 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002320 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302321 log.Fields{
2322 "intf-id": intfID,
2323 "onu-id": onuID,
2324 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002325 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302326 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002327 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002328
Neha Sharma96b7bf22020-06-15 10:37:32 +00002329 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002330 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002331 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002332 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002333 tpDownloadMsg,
2334 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302335 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002336 onuDev.deviceType,
2337 onuDev.deviceID,
2338 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002339 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302340 return olterrors.NewErrCommunication("send-techprofile-download-request",
2341 log.Fields{
2342 "from-adapter": f.deviceHandler.device.Type,
2343 "to-adapter": onuDev.deviceType,
2344 "onu-id": onuDev.deviceID,
2345 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002346 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002347 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302348 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302349}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002350
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302351//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002352func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302353
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002354 f.onuGemInfoLock.Lock()
2355 defer f.onuGemInfoLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002356 onugem := f.onuGemInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07002357 // If the ONU already exists in onuGemInfo list, nothing to do
2358 for _, onu := range onugem {
2359 if onu.OnuID == onuID && onu.SerialNumber == serialNum {
2360 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2361 log.Fields{"onuID": onuID,
2362 "serialNum": serialNum})
2363 return nil
2364 }
2365 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002366
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302367 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002368 f.onuGemInfo = append(f.onuGemInfo, onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002369 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002370 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302371 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002372 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302373 log.Fields{
2374 "intf-id": intfID,
2375 "onu-id": onuID,
2376 "serial-num": serialNum,
2377 "onu": onu,
2378 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002379 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002380}
2381
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302382//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302383func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002384
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002385 f.onuGemInfoLock.Lock()
2386 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002387
Neha Sharma96b7bf22020-06-15 10:37:32 +00002388 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302389 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002390 "gem-port-id": gemPort,
2391 "intf-id": intfID,
2392 "onu-id": onuID,
2393 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002394 "onu-gem": f.onuGemInfo})
2395 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302396 // update the gem to the local cache as well as to kv strore
2397 for idx, onu := range onugem {
2398 if onu.OnuID == onuID {
2399 // check if gem already exists , else update the cache and kvstore
2400 for _, gem := range onu.GemPorts {
2401 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002402 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302403 log.Fields{
2404 "gem": gemPort,
2405 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302406 return
2407 }
2408 }
2409 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002410 f.onuGemInfo = onugem
Girish Gowdra9602eb42020-09-09 15:50:39 -07002411 break
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302412 }
2413 }
npujarec5762e2020-01-01 14:08:48 +05302414 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302415 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002416 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302417 log.Fields{
2418 "intf-id": intfID,
2419 "onu-id": onuID,
2420 "gemPort": gemPort,
2421 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002422 return
2423 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002424 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302425 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002426 "gem-port-id": gemPort,
2427 "intf-id": intfID,
2428 "onu-id": onuID,
2429 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002430 "onu-gem": f.onuGemInfo})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002431}
2432
2433// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002434
2435//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 +00002436func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302437
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002438 f.onuGemInfoLock.RLock()
2439 defer f.onuGemInfoLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302440
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002441 logger.Debugw(ctx, "getting-onu-id-from-gem-port-and-pon-port",
Shrey Baid26912972020-04-16 21:02:31 +05302442 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002443 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002444 "onu-geminfo": f.onuGemInfo,
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002445 "intf-id": intfID,
2446 "gemport-id": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302447 // get onuid from the onugem info cache
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002448 onugem := f.onuGemInfo
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002449
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302450 for _, onu := range onugem {
2451 for _, gem := range onu.GemPorts {
2452 if gem == gemPortID {
2453 return onu.OnuID, nil
2454 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002455 }
2456 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002457 logger.Errorw(ctx, "onu-id-from-gem-port-not-found", log.Fields{
2458 "gem-port-id": gemPortID,
2459 "interface-id": intfID,
Kent Hagermane6ff1012020-07-14 15:07:53 -04002460 "all-gems-on-port": onugem,
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002461 })
Thomas Lee S94109f12020-03-03 16:39:29 +05302462 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002463 "interface-id": intfID,
2464 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00002465 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002466}
2467
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002468//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302469func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002470 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002471 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002472 var err error
2473
2474 if packetIn.IntfType == "pon" {
2475 // packet indication does not have serial number , so sending as nil
Neha Sharma96b7bf22020-06-15 10:37:32 +00002476 if onuID, err = f.getOnuIDfromGemPortMap(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002477 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002478 return logicalPortNum, err
2479 }
2480 if packetIn.PortNo != 0 {
2481 logicalPortNum = packetIn.PortNo
2482 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002483 uniID := uint32(0) // FIXME - multi-uni support
Neha Sharma96b7bf22020-06-15 10:37:32 +00002484 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002485 }
2486 // 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 +00002487 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002488 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002489 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002490 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002491 logger.Infow(ctx, "retrieved-logicalport-from-packet-in",
Shrey Baid26912972020-04-16 21:02:31 +05302492 log.Fields{
2493 "logical-port-num": logicalPortNum,
2494 "intf-type": packetIn.IntfType,
2495 "packet": hex.EncodeToString(packetIn.Pkt),
2496 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002497 return logicalPortNum, nil
2498}
2499
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002500//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002501func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002502 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002503
2504 ctag, priority, err := getCTagFromPacket(ctx, packet)
2505 if err != nil {
2506 return 0, err
2507 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302508
Esin Karaman7fb80c22020-07-16 14:23:33 +00002509 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002510 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002511 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002512 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002513 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302514 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002515 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302516 log.Fields{
2517 "pktinkey": pktInkey,
2518 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002519
2520 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002521 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302522 //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 +00002523 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302524 if err == nil {
2525 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002526 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302527 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002528 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002529 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302530 log.Fields{
2531 "pktinkey": pktInkey,
2532 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302533 return gemPortID, nil
2534 }
2535 }
Shrey Baid26912972020-04-16 21:02:31 +05302536 return uint32(0), olterrors.NewErrNotFound("gem-port",
2537 log.Fields{
2538 "pktinkey": pktInkey,
2539 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002540
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002541}
2542
David K. Bainbridge794735f2020-02-11 21:01:37 -08002543func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002544 logger.Debug(ctx, "adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002545 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002546 classifier[PacketTagType] = DoubleTag
2547 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002548 /* We manage flowId resource pool on per PON port basis.
2549 Since this situation is tricky, as a hack, we pass the NNI port
2550 index (network_intf_id) as PON port Index for the flowId resource
2551 pool. Also, there is no ONU Id available for trapping DHCP packets
2552 on NNI port, use onu_id as -1 (invalid)
2553 ****************** CAVEAT *******************
2554 This logic works if the NNI Port Id falls within the same valid
2555 range of PON Port Ids. If this doesn't work for some OLT Vendor
2556 we need to have a re-look at this.
2557 *********************************************
2558 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002559 onuID := -1
2560 uniID := -1
2561 gemPortID := -1
2562 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002563 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302564 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302565 return olterrors.NewErrNotFound("nni-intreface-id",
2566 log.Fields{
2567 "classifier": classifier,
2568 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002569 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302570 }
2571
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002572 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002573 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002574 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002575 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002576
David K. Bainbridge794735f2020-02-11 21:01:37 -08002577 classifierProto, err := makeOpenOltClassifierField(classifier)
2578 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002579 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002580 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002581 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002582 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002583 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002584 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002585 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002586 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002587 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2588 OnuId: int32(onuID), // OnuId not required
2589 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002590 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002591 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002592 AllocId: int32(allocID), // AllocId not used
2593 NetworkIntfId: int32(networkInterfaceID),
2594 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002595 Classifier: classifierProto,
2596 Action: actionProto,
2597 Priority: int32(logicalFlow.Priority),
2598 Cookie: logicalFlow.Cookie,
2599 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002600 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002601 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002602 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002603 logger.Info(ctx, "dhcp-trap-on-nni-flow-added–to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002604 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2605 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2606 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002607 }
2608 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002609}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002610
Esin Karamanae41e2b2019-12-17 18:13:13 +00002611//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2612func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2613 var packetType string
2614 ovid, ivid := false, false
2615 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2616 vid := vlanID & VlanvIDMask
2617 if vid != ReservedVlan {
2618 ovid = true
2619 }
2620 }
2621 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2622 vid := uint32(metadata)
2623 if vid != ReservedVlan {
2624 ivid = true
2625 }
2626 }
2627 if ovid && ivid {
2628 packetType = DoubleTag
2629 } else if !ovid && !ivid {
2630 packetType = Untagged
2631 } else {
2632 packetType = SingleTag
2633 }
2634 return packetType
2635}
2636
2637//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002638func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002639 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002640 action := make(map[string]interface{})
2641 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2642 action[TrapToHost] = true
2643 /* We manage flowId resource pool on per PON port basis.
2644 Since this situation is tricky, as a hack, we pass the NNI port
2645 index (network_intf_id) as PON port Index for the flowId resource
2646 pool. Also, there is no ONU Id available for trapping packets
2647 on NNI port, use onu_id as -1 (invalid)
2648 ****************** CAVEAT *******************
2649 This logic works if the NNI Port Id falls within the same valid
2650 range of PON Port Ids. If this doesn't work for some OLT Vendor
2651 we need to have a re-look at this.
2652 *********************************************
2653 */
2654 onuID := -1
2655 uniID := -1
2656 gemPortID := -1
2657 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002658 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002659 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302660 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002661 "classifier": classifier,
2662 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002663 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002664 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002665 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002666 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002667 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002668 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002669
David K. Bainbridge794735f2020-02-11 21:01:37 -08002670 classifierProto, err := makeOpenOltClassifierField(classifier)
2671 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002672 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002673 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002674 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002675 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002676 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002677 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002678 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002679 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002680 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2681 OnuId: int32(onuID), // OnuId not required
2682 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002683 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002684 FlowType: Downstream,
2685 AllocId: int32(allocID), // AllocId not used
2686 NetworkIntfId: int32(networkInterfaceID),
2687 GemportId: int32(gemPortID), // GemportId not used
2688 Classifier: classifierProto,
2689 Action: actionProto,
2690 Priority: int32(logicalFlow.Priority),
2691 Cookie: logicalFlow.Cookie,
2692 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002693 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002694 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002695 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002696 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002697 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2698 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2699 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002700 }
2701 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002702}
2703
salmansiddiqui7ac62132019-08-22 03:58:50 +00002704func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2705 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302706 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002707 }
2708 if Dir == tp_pb.Direction_UPSTREAM {
2709 return "upstream", nil
2710 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2711 return "downstream", nil
2712 }
2713 return "", nil
2714}
2715
Kent Hagermane6ff1012020-07-14 15:07:53 -04002716// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302717func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002718 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002719 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00002720 var gemPort uint32
2721 intfID := args[IntfID]
2722 onuID := args[OnuID]
2723 uniID := args[UniID]
2724 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002725 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002726 pbitToGem := make(map[uint32]uint32)
2727
2728 if len(gemPorts) == 1 {
2729 // If there is only single gemport use that and do not populate pbitToGem map
2730 gemPort = gemPorts[0]
2731 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2732 for idx, gemID := range gemPorts {
2733 switch TpInst := TpInst.(type) {
2734 case *tp.TechProfile:
2735 pBitMap := TpInst.UpstreamGemPortAttributeList[idx].PbitMap
2736 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2737 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2738 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2739 // this pcp bit traffic.
2740 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2741 if pbitSet == pbit1 {
2742 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2743 pbitToGem[pcp] = gemID
2744 }
2745 }
2746 default:
2747 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2748 return
2749 }
2750 }
2751 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
2752 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
2753 tp_pb.Direction_UPSTREAM,
2754 pcp.(uint32))
2755 }
2756
salmansiddiqui7ac62132019-08-22 03:58:50 +00002757 if ipProto, ok := classifierInfo[IPProto]; ok {
2758 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002759 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002760 "tp-id": tpID,
2761 "alloc-id": allocID,
2762 "intf-id": intfID,
2763 "onu-id": onuID,
2764 "uni-id": uniID,
2765 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002766 //Adding DHCP upstream flow
2767 if err := f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2768 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002769 }
2770
Girish Gowdra32625212020-04-29 11:26:35 -07002771 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002772 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302773 log.Fields{
2774 "intf-id": intfID,
2775 "onu-id": onuID,
2776 "uni-id": uniID,
2777 "classifier-info:": classifierInfo})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002778 if err := f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2779 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002780 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002781 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002782 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002783 return
2784 }
2785 } else if ethType, ok := classifierInfo[EthType]; ok {
2786 if ethType.(uint32) == EapEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002787 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002788 "intf-id": intfID,
2789 "onu-id": onuID,
2790 "uni-id": uniID,
2791 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002792 var vlanID uint32
2793 if val, ok := classifierInfo[VlanVid]; ok {
2794 vlanID = (val.(uint32)) & VlanvIDMask
2795 } else {
2796 vlanID = DefaultMgmtVlan
2797 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002798 if err := f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID, pbitToGem); err != nil {
2799 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002800 }
2801 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002802 } else if _, ok := actionInfo[PushVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002803 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002804 "intf-id": intfID,
2805 "onu-id": onuID,
2806 "uni-id": uniID,
2807 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002808 //Adding HSIA upstream flow
2809 if err := f.addUpstreamDataPathFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2810 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002811 }
2812 } else if _, ok := actionInfo[PopVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002813 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002814 "intf-id": intfID,
2815 "onu-id": onuID,
2816 "uni-id": uniID,
2817 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002818 //Adding HSIA downstream flow
2819 if err := f.addDownstreamDataPathFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2820 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002821 }
2822 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002823 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302824 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002825 "intf-id": intfID,
2826 "onu-id": onuID,
2827 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302828 "classifier": classifierInfo,
2829 "action": actionInfo,
2830 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002831 return
2832 }
2833 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002834 go func() {
2835 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
2836 logger.Warn(ctx, err)
2837 }
2838 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002839}
2840
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002841func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
2842 f.flowsUsedByGemPortKey.RLock()
2843 flowIDList := f.flowsUsedByGemPort[gemPortID]
2844 f.flowsUsedByGemPortKey.RUnlock()
2845 return len(flowIDList) > 1
2846
Gamze Abakafee36392019-10-03 11:17:24 +00002847}
2848
npujarec5762e2020-01-01 14:08:48 +05302849func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
2850 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002851 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2852 for _, currentGemPort := range currentGemPorts {
2853 for _, tpGemPort := range tpGemPorts {
2854 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2855 return true, currentGemPort
2856 }
2857 }
2858 }
Girish Gowdra54934262019-11-13 14:19:55 +05302859 if tpInst.InstanceCtrl.Onu == "single-instance" {
2860 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002861 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, onuID, uniID, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002862 logger.Warn(ctx, err)
2863 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002864 if err := f.DeleteTechProfileInstance(ctx, ponIntf, onuID, uniID, "", tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002865 logger.Warn(ctx, err)
2866 }
Girish Gowdra54934262019-11-13 14:19:55 +05302867
2868 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
2869 // still be used on other uni ports.
2870 // So, we need to check and make sure that no other gem port is referring to the given TP ID
2871 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002872 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002873 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302874 for i := 0; i < len(tpInstances); i++ {
2875 tpI := tpInstances[i]
2876 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05302877 for _, tpGemPort := range tpGemPorts {
2878 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002879 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302880 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05302881 }
2882 }
2883 }
2884 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002885 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00002886 return false, 0
2887}
2888
Neha Sharma96b7bf22020-06-15 10:37:32 +00002889func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002890 for _, field := range flows.GetOfbFields(flow) {
2891 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002892 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002893 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002894 } else if field.Type == flows.ETH_DST {
2895 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002896 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002897 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002898 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002899 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002900 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002901 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002902 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002903 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302904 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002905 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002906 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002907 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002908 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002909 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002910 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002911 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002912 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002913 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002914 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002915 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002916 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002917 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002918 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002919 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002920 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002921 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002922 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002923 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002924 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002925 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002926 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002927 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002928 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002929 return
2930 }
2931 }
2932}
2933
Neha Sharma96b7bf22020-06-15 10:37:32 +00002934func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002935 for _, action := range flows.GetActions(flow) {
2936 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002937 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002938 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002939 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002940 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002941 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002942 }
Scott Baker355d1742019-10-24 10:57:52 -07002943 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002944 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00002945 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002946 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002947 if out := action.GetPush(); out != nil {
2948 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002949 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002950 } else {
2951 actionInfo[PushVlan] = true
2952 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00002953 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05302954 log.Fields{
2955 "push-tpid": actionInfo[TPID].(uint32),
2956 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002957 }
2958 }
Scott Baker355d1742019-10-24 10:57:52 -07002959 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002960 if out := action.GetSetField(); out != nil {
2961 if field := out.GetField(); field != nil {
2962 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00002963 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002964 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002965 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
2966 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002967 }
2968 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002969 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002970 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002971 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002972 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002973 }
2974 }
2975 return nil
2976}
2977
Neha Sharma96b7bf22020-06-15 10:37:32 +00002978func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002979 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00002980 fieldtype := ofbField.GetType()
2981 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00002982 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2983 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002984 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002985 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002986 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002987 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00002988 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
2989 pcp := ofbField.GetVlanPcp()
2990 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002991 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002992 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002993 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00002994 }
2995 }
2996}
2997
Neha Sharma96b7bf22020-06-15 10:37:32 +00002998func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002999 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003000 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003001 } else {
3002 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003003 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003004 }
3005}
3006
Neha Sharma96b7bf22020-06-15 10:37:32 +00003007func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003008 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003009 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003010 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3011 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003012 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003013 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003014 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303015 log.Fields{
3016 "newinport": classifierInfo[InPort].(uint32),
3017 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003018 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303019 return olterrors.NewErrNotFound("child-in-port",
3020 log.Fields{
3021 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3022 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003023 }
3024 }
3025 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003026 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003027 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003028 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003029 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003030 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003031 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303032 log.Fields{
3033 "newoutport": actionInfo[Output].(uint32),
3034 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003035 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303036 return olterrors.NewErrNotFound("out-port",
3037 log.Fields{
3038 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3039 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003040 }
3041 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3042 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003043 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003044 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003045 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303046 log.Fields{
3047 "newinport": actionInfo[Output].(uint32),
3048 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003049 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303050 return olterrors.NewErrNotFound("nni-port",
3051 log.Fields{
3052 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3053 "in-port": classifierInfo[InPort].(uint32),
3054 "out-port": actionInfo[Output].(uint32),
3055 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003056 }
3057 }
3058 }
3059 return nil
3060}
Gamze Abakafee36392019-10-03 11:17:24 +00003061
Neha Sharma96b7bf22020-06-15 10:37:32 +00003062func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003063 /* Metadata 8 bytes:
3064 Most Significant 2 Bytes = Inner VLAN
3065 Next 2 Bytes = Tech Profile ID(TPID)
3066 Least Significant 4 Bytes = Port ID
3067 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3068 subscriber related flows.
3069 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003070 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003071 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003072 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003073 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003074 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003075 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003076}
3077
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003078func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3079 for _, sliceElement := range slice {
3080 if sliceElement == item {
3081 return slice
3082 }
3083 }
3084 return append(slice, item)
3085}
3086
3087func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003088 for _, sliceElement := range slice {
3089 if sliceElement == item {
3090 return slice
3091 }
3092 }
3093 return append(slice, item)
3094}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303095
3096// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003097func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303098
3099 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3100 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003101 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003102 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003103 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003104 log.Fields{
3105 "port-number": action[Output].(uint32),
3106 "error": err})
3107 return uint32(0), err
3108 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003109 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303110 return intfID, nil
3111 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003112 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003113 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003114 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003115 log.Fields{
3116 "port-number": action[Output].(uint32),
3117 "error": err})
3118 return uint32(0), err
3119 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003120 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303121 return intfID, nil
3122 }
3123 return uint32(0), nil
3124}
3125
3126// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003127func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3128 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3129 if err != nil {
3130 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3131 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3132 return
3133 }
3134 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003135
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003136 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003137 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003138 f.packetInGemPortLock.RUnlock()
3139
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303140 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003141 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003142 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 +05303143 log.Fields{
3144 "pktinkey": pktInkey,
3145 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003146 return
3147 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303148 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003149 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003150 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003151 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003152
npujarec5762e2020-01-01 14:08:48 +05303153 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003154 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 +05303155 log.Fields{
3156 "pktinkey": pktInkey,
3157 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303158}
3159
Esin Karaman7fb80c22020-07-16 14:23:33 +00003160//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3161func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3162 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003163 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003164 return 0, 0, errors.New("invalid packet length")
3165 }
3166 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3167 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3168
3169 var index int8
3170 if outerEthType == 0x8100 {
3171 if innerEthType == 0x8100 {
3172 // q-in-q 802.1ad or 802.1q double tagged packet.
3173 // get the inner vlanId
3174 index = 18
3175 } else {
3176 index = 14
3177 }
3178 priority := (packet[index] >> 5) & 0x7
3179 //13 bits composes vlanId value
3180 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3181 return vlan, priority, nil
3182 }
3183 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3184 return 0, 0, nil
3185}
3186
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303187// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303188func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003189
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003190 f.onuGemInfoLock.Lock()
3191 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003192
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003193 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303194 for idx, onu := range onugem {
3195 if onu.OnuID == onuID {
3196 for _, uni := range onu.UniPorts {
3197 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003198 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 +05303199 return
3200 }
3201 }
3202 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003203 f.onuGemInfo = onugem
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303204 }
3205 }
npujarec5762e2020-01-01 14:08:48 +05303206 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003207
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303208}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303209
npujarec5762e2020-01-01 14:08:48 +05303210func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3211 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303212 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003213 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303214 return
3215 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003216 f.flowsUsedByGemPortKey.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303217 for gem, FlowIDs := range flowIDsList {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003218 f.flowsUsedByGemPort[gem] = FlowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303219 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003220 f.flowsUsedByGemPortKey.Unlock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303221}
Esin Karamanccb714b2019-11-29 15:02:06 +00003222
Girish Gowdra9602eb42020-09-09 15:50:39 -07003223//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3224// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003225func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003226 classifierInfo := make(map[string]interface{})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003227 var flowInfo *rsrcMgr.FlowInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07003228 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
3229 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
3230
Esin Karamanccb714b2019-11-29 15:02:06 +00003231 if err != nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003232 logger.Warnw(ctx, "no-inport-found--cannot-release-resources-of-the-multicast-flow", log.Fields{"flowId:": flow.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003233 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00003234 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003235
3236 var onuID = int32(NoneOnuID)
3237 var uniID = int32(NoneUniID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003238 var flowID uint64
3239 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id); flowInfo == nil {
3240 return olterrors.NewErrPersistence("remove", "flow", flow.Id,
3241 log.Fields{
3242 "flow": flow,
3243 "device-id": f.deviceHandler.device.Id,
3244 "intf-id": networkInterfaceID,
3245 "onu-id": onuID}, err).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00003246 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003247 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: flowInfo.Flow.FlowType}
3248 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3249 log.Fields{
3250 "flow": flowInfo.Flow,
3251 "flow-id": flow.Id,
3252 "device-id": f.deviceHandler.device.Id})
3253 // Remove from device
3254 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3255 // DKB
3256 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3257 log.Fields{
3258 "flow-id": flow.Id,
3259 "error": err})
3260 return err
3261 }
3262 // Remove flow from KV store
3263 return f.resourceMgr.RemoveFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00003264}
3265
Girish Gowdra9602eb42020-09-09 15:50:39 -07003266func (f *OpenOltFlowMgr) incrementActiveFlowRemoveCount(ctx context.Context, flow *ofp.OfpFlowStats) {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003267
3268 f.pendingFlowRemoveDataPerSubscriberLock.Lock()
3269 defer f.pendingFlowRemoveDataPerSubscriberLock.Unlock()
3270
Girish Gowdra9602eb42020-09-09 15:50:39 -07003271 inPort, outPort := getPorts(flow)
3272 logger.Debugw(ctx, "increment-flow-remove-count-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
3273 if inPort != InvalidPort && outPort != InvalidPort {
3274 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
3275 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
3276 logger.Debugw(ctx, "increment-flow-remove-count-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3277
Girish Gowdra9602eb42020-09-09 15:50:39 -07003278 flowRemoveData, ok := f.pendingFlowRemoveDataPerSubscriber[key]
3279 if !ok {
3280 flowRemoveData = pendingFlowRemoveData{
3281 pendingFlowRemoveCount: 0,
3282 allFlowsRemoved: make(chan struct{}),
3283 }
3284 }
3285 flowRemoveData.pendingFlowRemoveCount++
3286 f.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
3287
3288 logger.Debugw(ctx, "current-flow-remove-count–increment",
3289 log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID,
3290 "currCnt": f.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
Esin Karamanccb714b2019-11-29 15:02:06 +00003291 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003292}
3293
Girish Gowdra9602eb42020-09-09 15:50:39 -07003294func (f *OpenOltFlowMgr) decrementActiveFlowRemoveCount(ctx context.Context, flow *ofp.OfpFlowStats) {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003295 f.pendingFlowRemoveDataPerSubscriberLock.Lock()
3296 defer f.pendingFlowRemoveDataPerSubscriberLock.Unlock()
3297
Girish Gowdra9602eb42020-09-09 15:50:39 -07003298 inPort, outPort := getPorts(flow)
3299 logger.Debugw(ctx, "decrement-flow-remove-count-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
3300 if inPort != InvalidPort && outPort != InvalidPort {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003301 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003302 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
3303 logger.Debugw(ctx, "decrement-flow-remove-count-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3304
Girish Gowdra9602eb42020-09-09 15:50:39 -07003305 if val, ok := f.pendingFlowRemoveDataPerSubscriber[key]; !ok {
3306 logger.Fatalf(ctx, "flow-remove-key-not-found", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3307 } else {
3308 if val.pendingFlowRemoveCount > 0 {
3309 val.pendingFlowRemoveCount--
3310 }
3311 logger.Debugw(ctx, "current-flow-remove-count-after-decrement",
3312 log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID,
3313 "currCnt": f.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
3314 // If all flow removes have finished, then close the channel to signal the receiver
3315 // to go ahead with flow adds.
3316 if val.pendingFlowRemoveCount == 0 {
3317 close(val.allFlowsRemoved)
3318 delete(f.pendingFlowRemoveDataPerSubscriber, key)
3319 return
3320 }
3321 f.pendingFlowRemoveDataPerSubscriber[key] = val
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003322 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003323 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003324}
3325
3326func (f *OpenOltFlowMgr) waitForFlowRemoveToFinish(ctx context.Context, flow *ofp.OfpFlowStats) {
3327 var flowRemoveData pendingFlowRemoveData
3328 var ok bool
3329 inPort, outPort := getPorts(flow)
3330 logger.Debugw(ctx, "wait-for-flow-remove-to-finish-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
3331 if inPort != InvalidPort && outPort != InvalidPort {
3332 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
3333 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
3334 logger.Debugw(ctx, "wait-for-flow-remove-to-finish-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3335
3336 f.pendingFlowRemoveDataPerSubscriberLock.RLock()
3337 if flowRemoveData, ok = f.pendingFlowRemoveDataPerSubscriber[key]; !ok {
3338 logger.Debugw(ctx, "no-pending-flow-to-remove", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3339 f.pendingFlowRemoveDataPerSubscriberLock.RUnlock()
3340 return
3341 }
3342 f.pendingFlowRemoveDataPerSubscriberLock.RUnlock()
3343
3344 // Wait for all flow removes to finish first
3345 <-flowRemoveData.allFlowsRemoved
3346
3347 logger.Debugw(ctx, "all-flows-cleared--handling-flow-add-now", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3348 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003349}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003350
3351// reconcileSubscriberDataPathFlowIDMap reconciles subscriberDataPathFlowIDMap from KV store
3352func (f *OpenOltFlowMgr) reconcileSubscriberDataPathFlowIDMap(ctx context.Context) {
3353 onuGemInfo, err := f.resourceMgr.GetOnuGemInfo(ctx, f.ponPortIdx)
3354 if err != nil {
3355 _ = olterrors.NewErrNotFound("onu", log.Fields{
3356 "pon-port": f.ponPortIdx}, err).Log()
3357 return
3358 }
3359
3360 f.subscriberDataPathFlowIDMapLock.Lock()
3361 defer f.subscriberDataPathFlowIDMapLock.Unlock()
3362
3363 for _, onu := range onuGemInfo {
3364 for _, uniID := range onu.UniPorts {
3365 flowIDs, err := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
3366 if err != nil {
3367 logger.Fatalf(ctx, "failed-to-read-flow-ids-of-onu-during-reconciliation")
3368 }
3369 for _, flowID := range flowIDs {
3370 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
3371 if flowInfo == nil {
3372 // Error is already logged in the called function
3373 continue
3374 }
3375 if flowInfo.Flow.Classifier.PktTagType == DoubleTag &&
3376 flowInfo.Flow.FlowType == Downstream &&
3377 flowInfo.Flow.Classifier.OVid > 0 &&
3378 flowInfo.Flow.TechProfileId > 0 {
3379 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3380 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3381 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3382 }
3383 } else if flowInfo.Flow.Classifier.PktTagType == SingleTag &&
3384 flowInfo.Flow.FlowType == Upstream &&
3385 flowInfo.Flow.Action.OVid > 0 &&
3386 flowInfo.Flow.TechProfileId > 0 {
3387 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3388 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3389 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3390 }
3391 }
3392 }
3393 }
3394 }
3395}
3396
3397// isDatapathFlow declares a flow as datapath flow if it is not a controller bound flow and the flow does not have group
3398func isDatapathFlow(flow *ofp.OfpFlowStats) bool {
3399 return !IsControllerBoundFlow(flows.GetOutPort(flow)) && !flows.HasGroup(flow)
3400}