blob: d68b8f8e2b8ce09ca10316c9c65d4e83ffbbce96 [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
22 "crypto/md5"
Matteo Scandolo6056e822019-11-13 14:05:29 -080023 "encoding/hex"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "encoding/json"
Girish Gowdracefae192020-03-19 18:14:10 -070025 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053026 "fmt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040027 "math/big"
Girish Gowdrafae935c2020-02-17 19:21:44 +053028 "strings"
William Kurkian740a09c2019-10-23 17:07:38 -040029 "sync"
Girish Gowdra3d633032019-12-10 16:37:05 +053030 "time"
Manikkaraj kb1d51442019-07-23 10:41:02 -040031
Esin Karamanccb714b2019-11-29 15:02:06 +000032 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v3/pkg/log"
34 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080035 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000036 "github.com/opencord/voltha-protos/v3/go/common"
37 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
38 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
39 openoltpb2 "github.com/opencord/voltha-protos/v3/go/openolt"
40 tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
41 "github.com/opencord/voltha-protos/v3/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040042
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040043 //deepcopy "github.com/getlantern/deepcopy"
Girish Gowdra3d633032019-12-10 16:37:05 +053044 "github.com/EagleChen/mapmutex"
Thomas Lee S94109f12020-03-03 16:39:29 +053045 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000046 "google.golang.org/grpc/codes"
47 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053048)
49
50const (
51 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070053 //HsiaFlow flow category
54 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053055
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070056 //EapolFlow flow category
57 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053058
Manikkaraj kb1d51442019-07-23 10:41:02 -040059 //DhcpFlow flow category
60 DhcpFlow = "DHCP_FLOW"
61
Esin Karamanccb714b2019-11-29 15:02:06 +000062 //MulticastFlow flow category
63 MulticastFlow = "MULTICAST_FLOW"
64
Esin Karamanae41e2b2019-12-17 18:13:13 +000065 //IgmpFlow flow category
66 IgmpFlow = "IGMP_FLOW"
67
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068 //IPProtoDhcp flow category
69 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053070
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070071 //IPProtoIgmp flow category
72 IPProtoIgmp = 2
73
74 //EapEthType eapethtype value
75 EapEthType = 0x888e
76 //LldpEthType lldp ethtype value
77 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000078 //IPv4EthType IPv4 ethernet type value
79 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070080
81 //IgmpProto proto value
82 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053083
Andrea Campanella7acc0b92020-02-14 09:20:49 +010084 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
85 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040086
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087 //DefaultMgmtVlan default vlan value
88 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053089
manikkaraj kbf256be2019-03-25 00:13:48 +053090 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070091
David K. Bainbridge82efc492019-09-04 09:57:11 -070092 //Upstream constant
93 Upstream = "upstream"
94 //Downstream constant
95 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000096 //Multicast constant
97 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070098 //PacketTagType constant
99 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700100 //Untagged constant
101 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700102 //SingleTag constant
103 SingleTag = "single_tag"
104 //DoubleTag constant
105 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +0530106
107 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108
109 //EthType constant
110 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +0000111 //EthDst constant
112 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113 //TPID constant
114 TPID = "tpid"
115 //IPProto constant
116 IPProto = "ip_proto"
117 //InPort constant
118 InPort = "in_port"
119 //VlanVid constant
120 VlanVid = "vlan_vid"
121 //VlanPcp constant
122 VlanPcp = "vlan_pcp"
123
124 //UDPDst constant
125 UDPDst = "udp_dst"
126 //UDPSrc constant
127 UDPSrc = "udp_src"
128 //Ipv4Dst constant
129 Ipv4Dst = "ipv4_dst"
130 //Ipv4Src constant
131 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700132 //Metadata constant
133 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700134 //TunnelID constant
135 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700136 //Output constant
137 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000138 //GroupID constant
139 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700140 // Actions
141
142 //PopVlan constant
143 PopVlan = "pop_vlan"
144 //PushVlan constant
145 PushVlan = "push_vlan"
146 //TrapToHost constant
147 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400148 //MaxMeterBand constant
149 MaxMeterBand = 2
150 //VlanPCPMask contant
151 VlanPCPMask = 0xFF
152 //VlanvIDMask constant
153 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000154 //IntfID constant
155 IntfID = "intfId"
156 //OnuID constant
157 OnuID = "onuId"
158 //UniID constant
159 UniID = "uniId"
160 //PortNo constant
161 PortNo = "portNo"
162 //AllocID constant
163 AllocID = "allocId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000164
165 //NoneOnuID constant
166 NoneOnuID = -1
167 //NoneUniID constant
168 NoneUniID = -1
169 //NoneGemPortID constant
170 NoneGemPortID = -1
Girish Gowdrafae935c2020-02-17 19:21:44 +0530171
172 // BinaryStringPrefix is binary string prefix
173 BinaryStringPrefix = "0b"
174 // BinaryBit1 is binary bit 1 expressed as a character
175 BinaryBit1 = '1'
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700176
177 // MapMutex
178 maxRetry = 300
179 maxDelay = 100000000
180 baseDelay = 10000000
181 factor = 1.1
182 jitter = 0.2
manikkaraj kbf256be2019-03-25 00:13:48 +0530183)
184
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400185type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700186 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400187 gemPort uint32
188}
189
Girish Gowdra3d633032019-12-10 16:37:05 +0530190type pendingFlowDeleteKey struct {
191 intfID uint32
192 onuID uint32
193 uniID uint32
194}
195
196type tpLockKey struct {
197 intfID uint32
198 onuID uint32
199 uniID uint32
200}
201
Gamze Abakafee36392019-10-03 11:17:24 +0000202type schedQueue struct {
203 direction tp_pb.Direction
204 intfID uint32
205 onuID uint32
206 uniID uint32
207 tpID uint32
208 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700209 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000210 meterID uint32
211 flowMetadata *voltha.FlowMetadata
212}
213
Esin Karamanccb714b2019-11-29 15:02:06 +0000214type queueInfoBrief struct {
215 gemPortID uint32
216 servicePriority uint32
217}
218
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700219//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530220type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000221 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000222 deviceHandler *DeviceHandler
223 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000224 onuIdsLock sync.RWMutex
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700225 perGemPortLock *mapmutex.Mutex // lock to be used to access the flowsUsedByGemPort map
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530226 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
227 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700228 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700229 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache, indexed by IntfId
230 // We need to have a global lock on the onuGemInfo map
231 onuGemInfoLock sync.RWMutex
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700232 pendingFlowDelete sync.Map
Girish Gowdra3d633032019-12-10 16:37:05 +0530233 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Esin Karamanccb714b2019-11-29 15:02:06 +0000234 perUserFlowHandleLock *mapmutex.Mutex
235 interfaceToMcastQueueMap map[uint32]*queueInfoBrief /*pon interface -> multicast queue map. Required to assign GEM to a bucket during group population*/
manikkaraj kbf256be2019-03-25 00:13:48 +0530236}
237
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700238//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
npujarec5762e2020-01-01 14:08:48 +0530239func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000240 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530241 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530242 var err error
243 var idx uint32
244
manikkaraj kbf256be2019-03-25 00:13:48 +0530245 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530246 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000247 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000248 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
249 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530250 return nil
251 }
William Kurkian740a09c2019-10-23 17:07:38 -0400252 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530253 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
254 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530255 ponPorts := rMgr.DevInfo.GetPonPorts()
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700256 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo, ponPorts)
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700257 flowMgr.onuGemInfoLock = sync.RWMutex{}
258 flowMgr.pendingFlowDelete = sync.Map{}
259 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(maxRetry, maxDelay, baseDelay, factor, jitter)
260 flowMgr.perGemPortLock = mapmutex.NewCustomizedMapMutex(maxRetry, maxDelay, baseDelay, factor, jitter)
261 flowMgr.interfaceToMcastQueueMap = make(map[uint32]*queueInfoBrief)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530262 //Load the onugem info cache from kv store on flowmanager start
263 for idx = 0; idx < ponPorts; idx++ {
npujarec5762e2020-01-01 14:08:48 +0530264 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000265 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530266 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530267 //Load flowID list per gem map per interface from the kvstore.
npujarec5762e2020-01-01 14:08:48 +0530268 flowMgr.loadFlowIDlistForGem(ctx, idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530269 }
Esin Karamanccb714b2019-11-29 15:02:06 +0000270 //load interface to multicast queue map from kv store
npujarec5762e2020-01-01 14:08:48 +0530271 flowMgr.loadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000272 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530273 return &flowMgr
274}
275
Kent Hagermane6ff1012020-07-14 15:07:53 -0400276func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000277 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700278 if f.perGemPortLock.TryLock(gemPK) {
279 logger.Debugw(ctx, "registering-flow-for-device ",
280 log.Fields{
281 "flow": flowFromCore,
282 "device-id": f.deviceHandler.device.Id})
283 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
284 if !ok {
285 flowIDList = []uint32{deviceFlow.FlowId}
286 }
287 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
288 f.flowsUsedByGemPort[gemPK] = flowIDList
289
290 f.perGemPortLock.Unlock(gemPK)
291
292 // update the flowids for a gem to the KVstore
293 return f.resourceMgr.UpdateFlowIDsForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Gamze Abakafee36392019-10-03 11:17:24 +0000294 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700295 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
296 log.Fields{
297 "flow-from-core": flowFromCore,
298 "device-id": f.deviceHandler.device.Id,
299 "key": gemPK,
300 })
301 return olterrors.NewErrAdapter("failed-to-acquire-per-gem-port-lock", log.Fields{
302 "flow-from-core": flowFromCore,
303 "device-id": f.deviceHandler.device.Id,
304 "key": gemPK,
305 }, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400306}
307
npujarec5762e2020-01-01 14:08:48 +0530308func (f *OpenOltFlowMgr) divideAndAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000309 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200310 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000311 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530312 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700313 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530314
Neha Sharma96b7bf22020-06-15 10:37:32 +0000315 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530316 "device-id": f.deviceHandler.device.Id,
317 "intf-id": intfID,
318 "onu-id": onuID,
319 "uni-id": uniID,
320 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700321 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530322 "action": actionInfo,
323 "usmeter-iD": UsMeterID,
324 "dsmeter-iD": DsMeterID,
325 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400326 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
327 // is because the flow is an NNI flow and there would be no onu resources associated with it
328 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400329 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200330 cause := "no-onu-id-for-flow"
331 fields := log.Fields{
332 "onu": onuID,
333 "port-no": portNo,
334 "classifer": classifierInfo,
335 "action": actionInfo,
336 "device-id": f.deviceHandler.device.Id}
337 logger.Errorw(ctx, cause, fields)
338 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530339 }
340
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700341 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000342 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530343 "uni": uni,
344 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530345
346 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
347 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000348 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530349 "device-id": f.deviceHandler.device.Id,
350 "intf-id": intfID,
351 "onu-id": onuID,
352 "uni-id": uniID,
353 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700354 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530355 "action": actionInfo,
356 "usmeter-id": UsMeterID,
357 "dsmeter-id": DsMeterID,
358 "tp-id": TpID})
npujarec5762e2020-01-01 14:08:48 +0530359 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530360 if allocID == 0 || gemPorts == nil || TpInst == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000361 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530362 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
Andrea Campanellabfe08432020-09-11 17:07:03 +0200363 return olterrors.NewErrNotFound(
364 "alloc-id-gem-ports-tp-unavailable",
365 nil, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +0530366 }
367 args := make(map[string]uint32)
368 args[IntfID] = intfID
369 args[OnuID] = onuID
370 args[UniID] = uniID
371 args[PortNo] = portNo
372 args[AllocID] = allocID
373
374 /* Flows can be added specific to gemport if p-bits are received.
375 * If no pbit mentioned then adding flows for all gemports
376 */
npujarec5762e2020-01-01 14:08:48 +0530377 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530378 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
379 } else {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200380 cause := "failed-to-acquire-per-user-flow-handle-lock"
381 fields := log.Fields{
382 "intf-id": intfID,
383 "onu-id": onuID,
384 "uni-id": uniID,
385 "flow-id": flow.Id,
386 "flow-cookie": flow.Cookie,
387 "device-id": f.deviceHandler.device.Id}
388 logger.Errorw(ctx, cause, fields)
389 return olterrors.NewErrAdapter(cause, fields, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400390 }
Andrea Campanellabfe08432020-09-11 17:07:03 +0200391 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530392}
393
salmansiddiqui7ac62132019-08-22 03:58:50 +0000394// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530395func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400396
Neha Sharma96b7bf22020-06-15 10:37:32 +0000397 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530398 log.Fields{"dir": sq.direction,
399 "intf-id": sq.intfID,
400 "onu-id": sq.onuID,
401 "uni-id": sq.uniID,
402 "tp-id": sq.tpID,
403 "meter-id": sq.meterID,
404 "tp-inst": sq.tpInst,
405 "flowmetadata": sq.flowMetadata,
406 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400407
Gamze Abakafee36392019-10-03 11:17:24 +0000408 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000409 if err != nil {
410 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400411 }
412
413 /* Lets make a simple assumption that if the meter-id is present on the KV store,
414 * then the scheduler and queues configuration is applied on the OLT device
415 * in the given direction.
416 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000417
Manikkaraj kb1d51442019-07-23 10:41:02 -0400418 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530419 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400420 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530421 return olterrors.NewErrNotFound("meter",
422 log.Fields{"intf-id": sq.intfID,
423 "onu-id": sq.onuID,
424 "uni-id": sq.uniID,
425 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400426 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000427
Manikkaraj kb1d51442019-07-23 10:41:02 -0400428 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000429 if KvStoreMeter.MeterId == sq.meterID {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000430 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400431 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530433 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800434 "unsupported": "meter-id",
435 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530436 "meter-id-in-flow": sq.meterID,
437 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400438 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000439
Neha Sharma96b7bf22020-06-15 10:37:32 +0000440 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530441 log.Fields{
442 "meter-id": sq.meterID,
443 "direction": Direction,
444 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000445
Gamze Abakafee36392019-10-03 11:17:24 +0000446 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000447 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000448 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000449 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400450 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000451
452 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530453 return olterrors.NewErrNotFound("scheduler-config",
454 log.Fields{
455 "intf-id": sq.intfID,
456 "direction": sq.direction,
457 "tp-inst": sq.tpInst,
458 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000459 }
460
Manikkaraj kb1d51442019-07-23 10:41:02 -0400461 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000462 if sq.flowMetadata != nil {
463 for _, meter := range sq.flowMetadata.Meters {
464 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400465 meterConfig = meter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000466 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Shrey Baid26912972020-04-16 21:02:31 +0530467 log.Fields{"meterConfig": meterConfig,
468 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400469 break
470 }
471 }
472 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000473 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400474 }
475 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530476 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800477 "reason": "Could-not-get-meterbands-from-flowMetadata",
478 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530479 "meter-id": sq.meterID,
480 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400481 } else if len(meterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000482 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Shrey Baid26912972020-04-16 21:02:31 +0530483 log.Fields{"Bands": meterConfig.Bands,
484 "meter-id": sq.meterID,
485 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530486 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800487 "reason": "Invalid-number-of-bands-in-meter",
488 "meterband-count": len(meterConfig.Bands),
489 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530490 "meter-id": sq.meterID,
491 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400492 }
493 cir := meterConfig.Bands[0].Rate
494 cbs := meterConfig.Bands[0].BurstSize
495 eir := meterConfig.Bands[1].Rate
496 ebs := meterConfig.Bands[1].BurstSize
497 pir := cir + eir
498 pbs := cbs + ebs
499 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
500
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700501 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000502 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503
npujarec5762e2020-01-01 14:08:48 +0530504 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530505 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
506 log.Fields{"intf-id": sq.intfID,
507 "direction": sq.direction,
508 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400509 }
510
salmansiddiqui7ac62132019-08-22 03:58:50 +0000511 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400512 * store the meter id on the KV store, for further reference.
513 */
npujarec5762e2020-01-01 14:08:48 +0530514 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 +0530515 return olterrors.NewErrAdapter("failed-updating-meter-id",
516 log.Fields{"onu-id": sq.onuID,
517 "meter-id": sq.meterID,
518 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400519 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000520 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530521 log.Fields{"direction": Direction,
522 "Meter": meterConfig,
523 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400524 return nil
525}
526
npujarec5762e2020-01-01 14:08:48 +0530527func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000528 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000529
530 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530531 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
532 log.Fields{"intf-id": sq.intfID,
533 "direction": sq.direction,
534 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000535 }
536
Neha Sharma96b7bf22020-06-15 10:37:32 +0000537 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530538 log.Fields{
539 "direction": sq.direction,
540 "TrafficScheds": TrafficSched,
541 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530542 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000543 IntfId: sq.intfID, OnuId: sq.onuID,
544 UniId: sq.uniID, PortNo: sq.uniPort,
545 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000546 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000547 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000548 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530549 "direction": sq.direction,
550 "traffic-queues": trafficQueues,
551 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000552
553 // On receiving the CreateTrafficQueues request, the driver should create corresponding
554 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000555 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530556 log.Fields{"direction": sq.direction,
557 "traffic-queues": trafficQueues,
558 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530559 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000560 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
561 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000562 TrafficQueues: trafficQueues,
563 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530564 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000565 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000566 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530567 "direction": sq.direction,
568 "traffic-queues": trafficQueues,
569 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000570
Esin Karamanccb714b2019-11-29 15:02:06 +0000571 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000572 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000573 if len(multicastTrafficQueues) > 0 {
574 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
575 //assumed that there is only one queue per PON for the multicast service
576 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
577 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000578 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000579 multicastQueuePerPonPort := multicastTrafficQueues[0]
580 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
581 gemPortID: multicastQueuePerPonPort.GemportId,
582 servicePriority: multicastQueuePerPonPort.Priority,
583 }
584 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400585 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
586 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
587 return err
588 }
Shrey Baid26912972020-04-16 21:02:31 +0530589
Neha Sharma96b7bf22020-06-15 10:37:32 +0000590 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000591 }
592 }
593 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000594 return nil
595}
596
salmansiddiqui7ac62132019-08-22 03:58:50 +0000597// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530598func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400599
600 var Direction string
601 var SchedCfg *tp_pb.SchedulerConfig
602 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000603 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530604 log.Fields{
605 "direction": sq.direction,
606 "intf-id": sq.intfID,
607 "onu-id": sq.onuID,
608 "uni-id": sq.uniID,
609 "uni-port": sq.uniPort,
610 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000611 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000612 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400613 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000614 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000615 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400616 Direction = "downstream"
617 }
618
Girish Kumar8f73fe02019-12-09 13:19:37 +0000619 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530620 return olterrors.NewErrNotFound("scheduler-config",
621 log.Fields{
622 "int-id": sq.intfID,
623 "direction": sq.direction,
624 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000625 }
626
npujarec5762e2020-01-01 14:08:48 +0530627 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400628 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530629 return olterrors.NewErrNotFound("meter",
630 log.Fields{
631 "onu-id": sq.onuID,
632 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400633 }
634 if KVStoreMeter == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000635 logger.Warnw(ctx, "no-meter-installed-yet",
Shrey Baid26912972020-04-16 21:02:31 +0530636 log.Fields{
637 "direction": Direction,
638 "intf-id": sq.intfID,
639 "onu-id": sq.onuID,
640 "uni-id": sq.uniID,
641 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400642 return nil
643 }
644 cir := KVStoreMeter.Bands[0].Rate
645 cbs := KVStoreMeter.Bands[0].BurstSize
646 eir := KVStoreMeter.Bands[1].Rate
647 ebs := KVStoreMeter.Bands[1].BurstSize
648 pir := cir + eir
649 pbs := cbs + ebs
650
651 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
652
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700653 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000654 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000655
Neha Sharma96b7bf22020-06-15 10:37:32 +0000656 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000657 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530658 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
659 log.Fields{
660 "intf-id": sq.intfID,
661 "direction": sq.direction,
662 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000663 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400664
npujarec5762e2020-01-01 14:08:48 +0530665 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000666 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
667 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000668 TrafficQueues: TrafficQueues,
669 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000670 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530671 log.Fields{
672 "intf-id": sq.intfID,
673 "traffic-queues": TrafficQueues,
674 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400675 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000676 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530677 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000678 IntfId: sq.intfID, OnuId: sq.onuID,
679 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400680 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000681 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530682 log.Fields{
683 "intf-id": sq.intfID,
684 "traffic-schedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400685 }
686
Neha Sharma96b7bf22020-06-15 10:37:32 +0000687 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000688
689 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400690 * delete the meter id on the KV store.
691 */
npujarec5762e2020-01-01 14:08:48 +0530692 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400693 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530694 return olterrors.NewErrAdapter("unable-to-remove-meter",
695 log.Fields{
696 "onu": sq.onuID,
697 "meter": KVStoreMeter.MeterId,
698 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400699 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000700 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530701 log.Fields{
702 "meter-id": KVStoreMeter.MeterId,
703 "dir": Direction,
704 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400705 return err
706}
707
Gamze Abakafee36392019-10-03 11:17:24 +0000708// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700709func (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 +0000710 var allocIDs []uint32
711 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530712 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530713 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000714 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000715
npujarec5762e2020-01-01 14:08:48 +0530716 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
717 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400718
Neha Sharma96b7bf22020-06-15 10:37:32 +0000719 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530720
Neha Sharma96b7bf22020-06-15 10:37:32 +0000721 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530722 "intf-id": intfID,
723 "onu-id": onuID,
724 "uni-id": uniID,
725 "device-id": f.deviceHandler.device.Id,
726 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530727
Manikkaraj kb1d51442019-07-23 10:41:02 -0400728 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530729 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000730 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000731 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530732 log.Fields{
733 "path": tpPath,
734 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530735 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000736 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530737 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000738 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530739 log.Fields{
740 "error": err,
741 "tp-id": TpID,
742 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000743 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530744 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400745 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
746 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
747 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530748 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000749 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530750 log.Fields{
751 "uni": uni,
752 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530753 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530754 }
Gamze Abakafee36392019-10-03 11:17:24 +0000755
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700756 switch tpInst := techProfileInstance.(type) {
757 case *tp.TechProfile:
758 if UsMeterID != 0 {
759 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
760 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
761 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000762 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700763 log.Fields{
764 "error": err,
765 "meter-id": UsMeterID,
766 "device-id": f.deviceHandler.device.Id})
767 return 0, nil, nil
768 }
769 }
770 if DsMeterID != 0 {
771 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
772 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
773 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000774 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700775 log.Fields{
776 "error": err,
777 "meter-id": DsMeterID,
778 "device-id": f.deviceHandler.device.Id})
779 return 0, nil, nil
780 }
781 }
782 allocID := tpInst.UsScheduler.AllocID
783 for _, gem := range tpInst.UpstreamGemPortAttributeList {
784 gemPortIDs = append(gemPortIDs, gem.GemportID)
785 }
786 allocIDs = appendUnique(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000787
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700788 if tpInstanceExists {
789 return allocID, gemPortIDs, techProfileInstance
790 }
791
792 for _, gemPortID := range gemPortIDs {
793 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
794 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000795 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700796 log.Fields{
797 "alloc-ids": allocIDs,
798 "gemports": allgemPortIDs,
799 "device-id": f.deviceHandler.device.Id})
800 // Send Tconts and GEM ports to KV store
801 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530802 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700803 case *tp.EponProfile:
804 // CreateSchedulerQueues for EPON needs to be implemented here
805 // when voltha-protos for EPON is completed.
806 allocID := tpInst.AllocID
807 for _, gem := range tpInst.UpstreamQueueAttributeList {
808 gemPortIDs = append(gemPortIDs, gem.GemportID)
809 }
810 allocIDs = appendUnique(allocIDs, allocID)
811
812 if tpInstanceExists {
813 return allocID, gemPortIDs, techProfileInstance
814 }
815
816 for _, gemPortID := range gemPortIDs {
817 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
818 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000819 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700820 log.Fields{
821 "alloc-ids": allocIDs,
822 "gemports": allgemPortIDs,
823 "device-id": f.deviceHandler.device.Id})
824 // Send Tconts and GEM ports to KV store
825 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
826 return allocID, gemPortIDs, techProfileInstance
827 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000828 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700829 log.Fields{
830 "tpInst": tpInst})
831 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530832 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530833}
834
npujarec5762e2020-01-01 14:08:48 +0530835func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530836
Neha Sharma96b7bf22020-06-15 10:37:32 +0000837 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530838 log.Fields{
839 "intf-id": intfID,
840 "onu-id": onuID,
841 "uni-id": uniID,
842 "alloc-id": allocID,
843 "gemport-ids": gemPortIDs,
844 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530845 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530846 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000847 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 +0530848 }
npujarec5762e2020-01-01 14:08:48 +0530849 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000850 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 +0530851 }
npujarec5762e2020-01-01 14:08:48 +0530852 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000853 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 +0530854 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000855 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 -0400856 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530857 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400858 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530859}
860
Neha Sharma96b7bf22020-06-15 10:37:32 +0000861func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000862 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530863 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000864 for _, intfID := range techRange.IntfIds {
865 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400866 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000867 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530868 log.Fields{
869 "intf-id": intfID,
870 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530871 }
872 }
873 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400874 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530875 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530876 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800877 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530878 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
879 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530880 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000881 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530882 log.Fields{
883 "numofTech": tpCount,
884 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
885 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530886 return nil
887}
888
npujarec5762e2020-01-01 14:08:48 +0530889func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530890 portNo uint32, uplinkClassifier map[string]interface{},
891 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000892 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700893 uplinkClassifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000894 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530895 log.Fields{
896 "uplinkClassifier": uplinkClassifier,
897 "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800898 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000899 Upstream, logicalFlow, allocID, gemportID, tpID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530900 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530901}
902
npujarec5762e2020-01-01 14:08:48 +0530903func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530904 portNo uint32, downlinkClassifier map[string]interface{},
905 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000906 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700907 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000908 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530909 log.Fields{
910 "downlinkClassifier": downlinkClassifier,
911 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400912 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
913 if vlan, exists := downlinkClassifier[VlanVid]; exists {
914 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700915 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Neha Sharma96b7bf22020-06-15 10:37:32 +0000916 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, intfID, onuID, uniID) {
917 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530918 log.Fields{
919 "flow": logicalFlow,
920 "device-id": f.deviceHandler.device.Id,
921 "onu-id": onuID,
922 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800923 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400924 }
925 }
926 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530927 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400928
Manikkaraj k884c1242019-04-11 16:26:42 +0530929 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700930 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400931 // vlan_vid is a uint32. must be type asserted as such or conversion fails
932 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530933 if ok {
934 downlinkAction[VlanVid] = dlClVid & 0xfff
935 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530936 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530937 "reason": "failed-to-convert-vlanid-classifier",
938 "vlan-id": VlanVid,
939 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530940 }
941
David K. Bainbridge794735f2020-02-11 21:01:37 -0800942 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000943 Downstream, logicalFlow, allocID, gemportID, tpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530944}
945
npujarec5762e2020-01-01 14:08:48 +0530946func (f *OpenOltFlowMgr) addHSIAFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530947 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000948 allocID uint32, gemPortID uint32, tpID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530949 /* One of the OLT platform (Broadcom BAL) requires that symmetric
950 flows require the same flow_id to be used across UL and DL.
951 Since HSIA flow is the only symmetric flow currently, we need to
952 re-use the flow_id across both direction. The 'flow_category'
953 takes priority over flow_cookie to find any available HSIA_FLOW
954 id for the ONU.
955 */
Neha Sharma96b7bf22020-06-15 10:37:32 +0000956 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530957 log.Fields{
958 "intf-id": intfID,
959 "onu-id": onuID,
960 "uni-id": uniID,
961 "device-id": f.deviceHandler.device.Id,
962 "classifier": classifier,
963 "action": action,
964 "direction": direction,
965 "alloc-id": allocID,
966 "gemport-id": gemPortID,
967 "logicalflow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530968 var vlanPbit uint32 = 0xff // means no pbit
Gamze Abaka724d0852020-03-18 12:10:24 +0000969 var vlanVid uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400970 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000971 vlanPbit = classifier[VlanPcp].(uint32)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000972 logger.Debugw(ctx, "found-pbit-in-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530973 log.Fields{
974 "vlan-pbit": vlanPbit,
975 "intf-id": intfID,
976 "onu-id": onuID,
977 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800978 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000979 logger.Debugw(ctx, "pbit-not-found-in-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530980 log.Fields{
981 "vlan-pcp": VlanPcp,
982 "intf-id": intfID,
983 "onu-id": onuID,
984 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400985 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000986 if _, ok := classifier[VlanVid]; ok {
987 vlanVid = classifier[VlanVid].(uint32)
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000988 logger.Debugw(ctx, "found-vlan-in-the-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530989 log.Fields{
990 "vlan-vid": vlanVid,
991 "intf-id": intfID,
992 "onu-id": onuID,
993 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000994 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000995 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530996 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000997 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +0530998 log.Fields{
999 "device-id": f.deviceHandler.device.Id,
1000 "intf-id": intfID,
1001 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001002 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301003 }
Gamze Abaka724d0852020-03-18 12:10:24 +00001004 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +05301005 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301006 return olterrors.NewErrNotFound("hsia-flow-id",
1007 log.Fields{
1008 "direction": direction,
1009 "device-id": f.deviceHandler.device.Id,
1010 "intf-id": intfID,
1011 "onu-id": onuID,
1012 }, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301013 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001014 classifierProto, err := makeOpenOltClassifierField(classifier)
1015 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301016 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301017 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001018 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301019 log.Fields{
1020 "classifier": *classifierProto,
1021 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001022 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001023 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301024 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301025 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001026 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301027 log.Fields{
1028 "action": *actionProto,
1029 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001030 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301031 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301032 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001033 log.Fields{
1034 "classifier": classifier,
1035 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301036 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001037 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301038 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001039 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
1040 OnuId: int32(onuID),
1041 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +00001042 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +05301043 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001044 AllocId: int32(allocID),
1045 NetworkIntfId: int32(networkIntfID),
1046 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +05301047 Classifier: classifierProto,
1048 Action: actionProto,
1049 Priority: int32(logicalFlow.Priority),
1050 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001051 PortNo: portNo,
1052 TechProfileId: tpID,
1053 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001054 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301055 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301056 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001057 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301058 log.Fields{"direction": direction,
1059 "device-id": f.deviceHandler.device.Id,
1060 "flow": flow,
1061 "intf-id": intfID,
1062 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001063 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
1064 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1065 flow.OnuId,
1066 flow.UniId,
1067 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301068 return olterrors.NewErrPersistence("update", "flow", flowID,
1069 log.Fields{
1070 "flow": flow,
1071 "device-id": f.deviceHandler.device.Id,
1072 "intf-id": intfID,
1073 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001074 }
1075 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301076}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001077
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001078func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1079 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1080 gemPortID uint32, tpID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301081
Neha Sharma96b7bf22020-06-15 10:37:32 +00001082 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301083 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301084 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001085 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301086 "action": action,
1087 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001088 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301089 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301090
1091 // Clear the action map
1092 for k := range action {
1093 delete(action, k)
1094 }
1095
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001096 action[TrapToHost] = true
1097 classifier[UDPSrc] = uint32(68)
1098 classifier[UDPDst] = uint32(67)
1099 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301100
Neha Sharma96b7bf22020-06-15 10:37:32 +00001101 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301102 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001103 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301104 log.Fields{
1105 "device-id": f.deviceHandler.device.Id,
1106 "intf-id": intfID,
1107 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001108 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301109 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301110
David K. Bainbridge794735f2020-02-11 21:01:37 -08001111 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, DhcpFlow, 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301112
1113 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301114 return olterrors.NewErrNotFound("flow",
1115 log.Fields{
1116 "interface-id": intfID,
1117 "gem-port": gemPortID,
1118 "cookie": flowStoreCookie,
1119 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001120 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301121 }
1122
Neha Sharma96b7bf22020-06-15 10:37:32 +00001123 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301124 log.Fields{
1125 "ul_classifier": classifier,
1126 "ul_action": action,
1127 "uplinkFlowId": flowID,
1128 "intf-id": intfID,
1129 "onu-id": onuID,
1130 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301131
David K. Bainbridge794735f2020-02-11 21:01:37 -08001132 classifierProto, err := makeOpenOltClassifierField(classifier)
1133 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301134 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301135 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001136 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001137 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001138 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301139 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301140 }
1141
David K. Bainbridge794735f2020-02-11 21:01:37 -08001142 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001143 OnuId: int32(onuID),
1144 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301145 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001146 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001147 AllocId: int32(allocID),
1148 NetworkIntfId: int32(networkIntfID),
1149 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301150 Classifier: classifierProto,
1151 Action: actionProto,
1152 Priority: int32(logicalFlow.Priority),
1153 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001154 PortNo: portNo,
1155 TechProfileId: tpID,
1156 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001157 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301158 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001159 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001160 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301161 log.Fields{
1162 "device-id": f.deviceHandler.device.Id,
1163 "flow-id": flowID,
1164 "intf-id": intfID,
1165 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001166 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
1167 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
1168 dhcpFlow.OnuId,
1169 dhcpFlow.UniId,
1170 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301171 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1172 log.Fields{
1173 "flow": dhcpFlow,
1174 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301175 }
1176
David K. Bainbridge794735f2020-02-11 21:01:37 -08001177 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301178}
1179
Esin Karamanae41e2b2019-12-17 18:13:13 +00001180//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301181func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001182 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32) error {
1183 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001184}
1185
1186//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301187func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001188 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string, tpID uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001189
Neha Sharma96b7bf22020-06-15 10:37:32 +00001190 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001191 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301192 return olterrors.NewErrNotFound("nni-interface-id",
1193 log.Fields{
1194 "classifier": classifier,
1195 "action": action,
1196 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001197 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001198 }
1199
1200 // Clear the action map
1201 for k := range action {
1202 delete(action, k)
1203 }
1204
1205 action[TrapToHost] = true
1206 classifier[PacketTagType] = SingleTag
1207 delete(classifier, VlanVid)
1208
Neha Sharma96b7bf22020-06-15 10:37:32 +00001209 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301210 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001211 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001212 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001213 }
1214
npujarec5762e2020-01-01 14:08:48 +05301215 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, flowType, 0, 0 /*classifier[VLAN_PCP].(uint32)*/)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001216
1217 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301218 return olterrors.NewErrNotFound("flow-id",
1219 log.Fields{
1220 "intf-id": intfID,
1221 "oni-id": onuID,
1222 "cookie": flowStoreCookie,
1223 "flow-type": flowType,
1224 "device-id": f.deviceHandler.device.Id,
1225 "onu-id": onuID},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001226 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001227 }
1228
Neha Sharma96b7bf22020-06-15 10:37:32 +00001229 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301230 log.Fields{
1231 "ul_classifier": classifier,
1232 "ul_action": action,
1233 "uplinkFlowId": flowID,
1234 "flowType": flowType,
1235 "device-id": f.deviceHandler.device.Id,
1236 "intf-id": intfID,
1237 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001238
David K. Bainbridge794735f2020-02-11 21:01:37 -08001239 classifierProto, err := makeOpenOltClassifierField(classifier)
1240 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301241 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001242 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001243 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301244 log.Fields{
1245 "classifier": *classifierProto,
1246 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001247 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001248 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301249 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001250 }
1251
David K. Bainbridge794735f2020-02-11 21:01:37 -08001252 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001253 OnuId: int32(onuID),
1254 UniId: int32(uniID),
1255 FlowId: flowID,
1256 FlowType: Upstream,
1257 AllocId: int32(allocID),
1258 NetworkIntfId: int32(networkIntfID),
1259 GemportId: int32(gemPortID),
1260 Classifier: classifierProto,
1261 Action: actionProto,
1262 Priority: int32(logicalFlow.Priority),
1263 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001264 PortNo: portNo,
1265 TechProfileId: tpID,
1266 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001267
David K. Bainbridge794735f2020-02-11 21:01:37 -08001268 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301269 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001270 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001271 logger.Infof(ctx, "%s ul-flow-added-to-device-successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001272
David K. Bainbridge794735f2020-02-11 21:01:37 -08001273 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
1274 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1275 flow.OnuId,
1276 flow.UniId,
1277 flow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301278 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 +00001279 }
1280
David K. Bainbridge794735f2020-02-11 21:01:37 -08001281 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001282}
1283
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001284// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001285func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1286 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1287 gemPortID uint32, vlanID uint32, tpID uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001288 logger.Infow(ctx, "adding-eapol-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301289 log.Fields{
1290 "intf-id": intfID,
1291 "onu-id": onuID,
1292 "port-no": portNo,
1293 "alloc-id": allocID,
1294 "gemport-id": gemPortID,
1295 "vlan-id": vlanID,
1296 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301297
1298 uplinkClassifier := make(map[string]interface{})
1299 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301300
manikkaraj kbf256be2019-03-25 00:13:48 +05301301 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001302 uplinkClassifier[EthType] = uint32(EapEthType)
1303 uplinkClassifier[PacketTagType] = SingleTag
1304 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001305 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301306 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001307 uplinkAction[TrapToHost] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00001308 flowStoreCookie := getFlowStoreCookie(ctx, uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301309 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001310 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301311 "device-id": f.deviceHandler.device.Id,
1312 "onu-id": onuID,
1313 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001314 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301315 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301316 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +00001317 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +05301318 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301319 return olterrors.NewErrNotFound("flow-id",
1320 log.Fields{
1321 "intf-id": intfID,
1322 "onu-id": onuID,
1323 "coookie": flowStoreCookie,
1324 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001325 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301326 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001327 logger.Debugw(ctx, "creating-ul-eapol-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301328 log.Fields{
1329 "ul_classifier": uplinkClassifier,
1330 "ul_action": uplinkAction,
1331 "uplinkFlowId": uplinkFlowID,
1332 "device-id": f.deviceHandler.device.Id,
1333 "intf-id": intfID,
1334 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301335
David K. Bainbridge794735f2020-02-11 21:01:37 -08001336 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1337 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301338 return olterrors.NewErrInvalidValue(log.Fields{
1339 "classifier": uplinkClassifier,
1340 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301341 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001342 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301343 log.Fields{
1344 "classifier": *classifierProto,
1345 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001346 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001347 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301348 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301349 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001350 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301351 log.Fields{
1352 "action": *actionProto,
1353 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001354 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301355 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301356 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001357 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301358 "action": action,
1359 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001360 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301361 }
1362
David K. Bainbridge794735f2020-02-11 21:01:37 -08001363 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001364 OnuId: int32(onuID),
1365 UniId: int32(uniID),
1366 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001367 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001368 AllocId: int32(allocID),
1369 NetworkIntfId: int32(networkIntfID),
1370 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301371 Classifier: classifierProto,
1372 Action: actionProto,
1373 Priority: int32(logicalFlow.Priority),
1374 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001375 PortNo: portNo,
1376 TechProfileId: tpID,
1377 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001378 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301379 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001380 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001381 logger.Infow(ctx, "eapol-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301382 log.Fields{
1383 "device-id": f.deviceHandler.device.Id,
1384 "onu-id": onuID,
1385 "intf-id": intfID,
1386 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001387 flowCategory := "EAPOL"
1388 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1389 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1390 upstreamFlow.OnuId,
1391 upstreamFlow.UniId,
1392 upstreamFlow.FlowId,
1393 /* lowCategory, */
1394 flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301395 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1396 log.Fields{
1397 "flow": upstreamFlow,
1398 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301399 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001400 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301401}
1402
David K. Bainbridge794735f2020-02-11 21:01:37 -08001403func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001404 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001405
1406 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1407 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1408 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001409 if vlanID != ReservedVlan {
1410 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001411 classifier.OVid = vid
1412 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301413 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001414 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1415 vid := uint32(metadata)
1416 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001417 classifier.IVid = vid
1418 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301419 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301420 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001421 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301422 classifier.OPbits = vlanPcp
1423 } else {
1424 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301425 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001426 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1427 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1428 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1429 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001430 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001431 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1432 classifier.PktTagType = pktTagType
1433
1434 switch pktTagType {
1435 case SingleTag:
1436 case DoubleTag:
1437 case Untagged:
1438 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001439 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301440 }
1441 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001442 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301443}
1444
Gamze Abaka724d0852020-03-18 12:10:24 +00001445func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001446 var actionCmd openoltpb2.ActionCmd
1447 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301448 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001449 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301450 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001451 if _, ok := actionInfo[VlanPcp]; ok {
1452 action.Cmd.RemarkInnerPbits = true
1453 action.IPbits = actionInfo[VlanPcp].(uint32)
1454 if _, ok := actionInfo[VlanVid]; ok {
1455 action.Cmd.TranslateInnerTag = true
1456 action.IVid = actionInfo[VlanVid].(uint32)
1457 }
1458 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001459 } else if _, ok := actionInfo[PushVlan]; ok {
1460 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301461 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001462 if _, ok := actionInfo[VlanPcp]; ok {
1463 action.OPbits = actionInfo[VlanPcp].(uint32)
1464 action.Cmd.RemarkOuterPbits = true
1465 if _, ok := classifierInfo[VlanVid]; ok {
1466 action.IVid = classifierInfo[VlanVid].(uint32)
1467 action.Cmd.TranslateInnerTag = true
1468 }
1469 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001470 } else if _, ok := actionInfo[TrapToHost]; ok {
1471 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301472 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001473 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301474 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001475 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301476}
1477
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001478// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001479func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1480 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301481}
1482
Gamze Abakafee36392019-10-03 11:17:24 +00001483// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301484func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1485 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001486 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1487
Gamze Abakafee36392019-10-03 11:17:24 +00001488 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301489 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001490 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301491 // return err
1492 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001493 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001494 logger.Debugw(ctx, "tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001495 }
1496 return nil
1497}
1498
1499// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301500func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001501 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001502 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001503 }
npujarec5762e2020-01-01 14:08:48 +05301504 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301505 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1506 log.Fields{
1507 "tp-id": tpID,
1508 "uni-port-name": uniPortName,
1509 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001510 }
1511 return nil
1512}
1513
Neha Sharma96b7bf22020-06-15 10:37:32 +00001514func getFlowStoreCookie(ctx context.Context, classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301515 if len(classifier) == 0 { // should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00001516 logger.Error(ctx, "invalid-classfier-object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301517 return 0
1518 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001519 logger.Debugw(ctx, "generating-flow-store-cookie",
Shrey Baid26912972020-04-16 21:02:31 +05301520 log.Fields{
1521 "classifier": classifier,
1522 "gemport-id": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301523 var jsonData []byte
1524 var flowString string
1525 var err error
1526 // TODO: Do we need to marshall ??
1527 if jsonData, err = json.Marshal(classifier); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001528 logger.Error(ctx, "failed-to-encode-classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301529 return 0
1530 }
1531 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001532 if gemPortID != 0 {
1533 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301534 }
1535 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001536 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301537 hash := big.NewInt(0)
1538 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301539 generatedHash := hash.Uint64()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001540 logger.Debugw(ctx, "hash-generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301541 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301542}
1543
npujarec5762e2020-01-01 14:08:48 +05301544func (f *OpenOltFlowMgr) getUpdatedFlowInfo(ctx context.Context, flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32, logicalFlowID uint64) *[]rsrcMgr.FlowInfo {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301545 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001546 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001547 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1548 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1549 */
1550 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001551 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001552 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001553 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001554 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001555 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301556 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001557 if existingFlows != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001558 logger.Debugw(ctx, "flow-exists-for-given-flowID--appending-it-to-current-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301559 log.Fields{
1560 "flow-id": flow.FlowId,
1561 "device-id": f.deviceHandler.device.Id,
1562 "intf-id": intfID,
1563 "onu-id": flow.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001564 //for _, f := range *existingFlows {
1565 // flows = append(flows, f)
1566 //}
1567 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001568 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001569 logger.Debugw(ctx, "updated-flows-for-given-flowID-and-onuid",
Shrey Baid26912972020-04-16 21:02:31 +05301570 log.Fields{
1571 "updatedflow": flows,
1572 "flow-id": flow.FlowId,
1573 "onu-id": flow.OnuId,
1574 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +05301575 return &flows
1576}
1577
npujarec5762e2020-01-01 14:08:48 +05301578func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(ctx context.Context, intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001579 logger.Debugw(ctx, "storing-flow(s)-into-kv-store", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301580 "flow-id": flowID,
1581 "device-id": f.deviceHandler.device.Id,
1582 "intf-id": intfID,
1583 "onu-id": onuID})
npujarec5762e2020-01-01 14:08:48 +05301584 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001585 logger.Warnw(ctx, "error-while-storing-flow-into-kv-store", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301586 "device-id": f.deviceHandler.device.Id,
1587 "onu-id": onuID,
1588 "intf-id": intfID,
1589 "flow-id": flowID})
manikkaraj k17652a72019-05-06 09:06:36 -04001590 return err
1591 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001592 logger.Infow(ctx, "stored-flow(s)-into-kv-store-successfully!", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301593 "device-id": f.deviceHandler.device.Id,
1594 "onu-id": onuID,
1595 "intf-id": intfID,
1596 "flow-id": flowID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301597 return nil
1598}
1599
David K. Bainbridge794735f2020-02-11 21:01:37 -08001600func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001601
1602 var intfID uint32
1603 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1604 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1605 */
1606 if deviceFlow.AccessIntfId != -1 {
1607 intfID = uint32(deviceFlow.AccessIntfId)
1608 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001609 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001610 intfID = uint32(deviceFlow.NetworkIntfId)
1611 }
1612
Neha Sharma96b7bf22020-06-15 10:37:32 +00001613 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301614 "flow": *deviceFlow,
1615 "device-id": f.deviceHandler.device.Id,
1616 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001617 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001618
1619 st, _ := status.FromError(err)
1620 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001621 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001622 "err": err,
1623 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301624 "device-id": f.deviceHandler.device.Id,
1625 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001626 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301627 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001628
1629 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001630 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301631 log.Fields{"err": err,
1632 "device-flow": deviceFlow,
1633 "device-id": f.deviceHandler.device.Id,
1634 "intf-id": intfID})
npujarec5762e2020-01-01 14:08:48 +05301635 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001636 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001637 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301638 if deviceFlow.GemportId != -1 {
1639 // No need to register the flow if it is a trap on nni flow.
Kent Hagermane6ff1012020-07-14 15:07:53 -04001640 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1641 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1642 return err
1643 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301644 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001645 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301646 log.Fields{
1647 "flow": *deviceFlow,
1648 "device-id": f.deviceHandler.device.Id,
1649 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001650 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001651}
1652
Neha Sharma96b7bf22020-06-15 10:37:32 +00001653func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1654 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301655 log.Fields{
1656 "flow": *deviceFlow,
1657 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001658 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001659 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001660 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001661 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301662 log.Fields{
1663 "err": err,
1664 "deviceFlow": deviceFlow,
1665 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001666 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001667 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001668 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001669 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001670
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001671 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001672 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001673 "of-flow-id": ofFlowID,
1674 "flow": *deviceFlow,
1675 "device-id": f.deviceHandler.device.Id,
1676 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001677 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301678}
1679
David K. Bainbridge794735f2020-02-11 21:01:37 -08001680func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001681
1682 classifierInfo := make(map[string]interface{})
1683 actionInfo := make(map[string]interface{})
1684
1685 classifierInfo[EthType] = uint32(LldpEthType)
1686 classifierInfo[PacketTagType] = Untagged
1687 actionInfo[TrapToHost] = true
1688
1689 // LLDP flow is installed to trap LLDP packets on the NNI port.
1690 // We manage flow_id resource pool on per PON port basis.
1691 // Since this situation is tricky, as a hack, we pass the NNI port
1692 // index (network_intf_id) as PON port Index for the flow_id resource
1693 // pool. Also, there is no ONU Id available for trapping LLDP packets
1694 // on NNI port, use onu_id as -1 (invalid)
1695 // ****************** CAVEAT *******************
1696 // This logic works if the NNI Port Id falls within the same valid
1697 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1698 // we need to have a re-look at this.
1699 // *********************************************
1700
1701 var onuID = -1
1702 var uniID = -1
1703 var gemPortID = -1
1704
Neha Sharma96b7bf22020-06-15 10:37:32 +00001705 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001706 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301707 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001708 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001709 var flowStoreCookie = getFlowStoreCookie(ctx, classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301710 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001711 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001712 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001713 }
npujarec5762e2020-01-01 14:08:48 +05301714 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001715
1716 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301717 return olterrors.NewErrNotFound("flow-id",
1718 log.Fields{
1719 "interface-id": networkInterfaceID,
1720 "onu-id": onuID,
1721 "uni-id": uniID,
1722 "gem-port-id": gemPortID,
1723 "cookie": flowStoreCookie,
1724 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001725 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001726 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001727 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1728 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301729 return olterrors.NewErrInvalidValue(
1730 log.Fields{
1731 "classifier": classifierInfo,
1732 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001733 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001734 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301735 log.Fields{
1736 "classifier": *classifierProto,
1737 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001738 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001739 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301740 return olterrors.NewErrInvalidValue(
1741 log.Fields{
1742 "action": actionInfo,
1743 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001744 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001745 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301746 log.Fields{
1747 "action": *actionProto,
1748 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001749
1750 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1751 OnuId: int32(onuID), // OnuId not required
1752 UniId: int32(uniID), // UniId not used
1753 FlowId: flowID,
1754 FlowType: Downstream,
1755 NetworkIntfId: int32(networkInterfaceID),
1756 GemportId: int32(gemPortID),
1757 Classifier: classifierProto,
1758 Action: actionProto,
1759 Priority: int32(flow.Priority),
1760 Cookie: flow.Cookie,
1761 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001762 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301763 return olterrors.NewErrFlowOp("add", flowID,
1764 log.Fields{
1765 "flow": downstreamflow,
1766 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001767 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001768 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301769 log.Fields{
1770 "device-id": f.deviceHandler.device.Id,
1771 "onu-id": onuID,
1772 "flow-id": flowID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001773 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1774 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1775 int32(onuID),
1776 int32(uniID),
1777 flowID, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301778 return olterrors.NewErrPersistence("update", "flow", flowID,
1779 log.Fields{
1780 "flow": downstreamflow,
1781 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001782 }
1783 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301784}
1785
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001786func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1787 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001788}
1789
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001790//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001791func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001792 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1793 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1794 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001795 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301796 log.Fields{
1797 "intf-id": intfID,
1798 "onu-id": onuID,
1799 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001800 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001801 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301802 return nil, olterrors.NewErrNotFound("onu-child-device",
1803 log.Fields{
1804 "onu-id": onuID,
1805 "intf-id": intfID,
1806 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001807 }
1808 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1809 //better to ad the device to cache here.
1810 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1811 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001812 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301813 log.Fields{
1814 "intf-id": intfID,
1815 "onu-id": onuID,
1816 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001817 }
1818
1819 return onuDev.(*OnuDevice), nil
1820}
1821
1822//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001823func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1824 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301825 log.Fields{
1826 "pon-port": intfID,
1827 "onu-id": onuID,
1828 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001829 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001830 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001831 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301832 return nil, olterrors.NewErrNotFound("onu",
1833 log.Fields{
1834 "interface-id": parentPortNo,
1835 "onu-id": onuID,
1836 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001837 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301838 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001839 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301840 log.Fields{
1841 "device-id": f.deviceHandler.device.Id,
1842 "child_device_id": onuDevice.Id,
1843 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301844 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301845}
1846
Neha Sharma96b7bf22020-06-15 10:37:32 +00001847func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1848 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301849 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001850 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301851 log.Fields{
1852 "intf-id": intfID,
1853 "onu-id": onuID,
1854 "uni-id": uniID,
1855 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001856 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301857 }
1858
1859 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001860 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301861 log.Fields{
1862 "msg": *delGemPortMsg,
1863 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001864 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301865 delGemPortMsg,
1866 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301867 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001868 onuDev.deviceType,
1869 onuDev.deviceID,
1870 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301871 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1872 log.Fields{
1873 "from-adapter": f.deviceHandler.device.Type,
1874 "to-adapter": onuDev.deviceType,
1875 "onu-id": onuDev.deviceID,
1876 "proxyDeviceID": onuDev.proxyDeviceID,
1877 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301878 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001879 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301880 log.Fields{
1881 "msg": delGemPortMsg,
1882 "from-adapter": f.deviceHandler.device.Type,
1883 "to-adapter": onuDev.deviceType,
1884 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301885 return nil
1886}
1887
Neha Sharma96b7bf22020-06-15 10:37:32 +00001888func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1889 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301890 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001891 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301892 log.Fields{
1893 "intf-id": intfID,
1894 "onu-id": onuID,
1895 "uni-id": uniID,
1896 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001897 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301898 }
1899
1900 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001901 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301902 log.Fields{
1903 "msg": *delTcontMsg,
1904 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001905 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301906 delTcontMsg,
1907 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301908 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001909 onuDev.deviceType,
1910 onuDev.deviceID,
1911 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301912 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1913 log.Fields{
1914 "from-adapter": f.deviceHandler.device.Type,
1915 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1916 "proxyDeviceID": onuDev.proxyDeviceID,
1917 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301918 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001919 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301920 log.Fields{
1921 "msg": delTcontMsg,
1922 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301923 return nil
1924}
1925
Neha Sharma96b7bf22020-06-15 10:37:32 +00001926func (f *OpenOltFlowMgr) deletePendingFlows(ctx context.Context, Intf uint32, onuID int32, uniID int32) {
Girish Gowdra3d633032019-12-10 16:37:05 +05301927 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1928 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1929 if val.(int) > 0 {
1930 pnFlDels := val.(int) - 1
1931 if pnFlDels > 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001932 logger.Debugw(ctx, "flow-delete-succeeded--more-pending",
Shrey Baid26912972020-04-16 21:02:31 +05301933 log.Fields{
1934 "intf": Intf,
1935 "onu-id": onuID,
1936 "uni-id": uniID,
1937 "currpendingflowcnt": pnFlDels,
1938 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301939 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1940 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001941 logger.Debugw(ctx, "all-pending-flow-deletes-handled--removing-entry-from-map",
Shrey Baid26912972020-04-16 21:02:31 +05301942 log.Fields{
1943 "intf": Intf,
1944 "onu-id": onuID,
1945 "uni-id": uniID,
1946 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301947 f.pendingFlowDelete.Delete(pnFlDelKey)
1948 }
1949 }
1950 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001951 logger.Debugw(ctx, "no-pending-delete-flows-found",
Shrey Baid26912972020-04-16 21:02:31 +05301952 log.Fields{
1953 "intf": Intf,
1954 "onu-id": onuID,
1955 "uni-id": uniID,
1956 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301957
1958 }
1959
1960}
1961
Girish Gowdrac3037402020-01-22 20:29:53 +05301962// Once the gemport is released for a given onu, it also has to be cleared from local cache
1963// which was used for deriving the gemport->logicalPortNo during packet-in.
1964// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1965// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001966func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001967
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001968 f.onuGemInfoLock.Lock()
1969 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001970
Neha Sharma96b7bf22020-06-15 10:37:32 +00001971 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301972 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001973 "gem-port-id": gemPortID,
1974 "intf-id": intfID,
1975 "onu-id": onuID,
1976 "device-id": f.deviceHandler.device.Id,
1977 "onu-gem": f.onuGemInfo[intfID]})
Girish Gowdrac3037402020-01-22 20:29:53 +05301978 onugem := f.onuGemInfo[intfID]
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001979deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001980 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301981 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001982 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301983 // If the gemport is found, delete it from local cache.
1984 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001985 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1986 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001987 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301988 log.Fields{
1989 "intf-id": intfID,
1990 "onu-id": onuID,
1991 "deletedgemport-id": gemPortID,
1992 "gemports": onu.GemPorts,
1993 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001994 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301995 }
1996 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001997 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301998 }
1999 }
2000}
2001
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302002//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002003// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302004func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302005 gemPortID int32, flowID uint32, flowDirection string,
2006 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002007
Neha Sharma96b7bf22020-06-15 10:37:32 +00002008 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002009 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302010 return olterrors.NewErrNotFound("tp-id",
2011 log.Fields{
2012 "flow": flow,
2013 "intf": Intf,
2014 "onu-id": onuID,
2015 "uni-id": uniID,
2016 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002017 }
Gamze Abakafee36392019-10-03 11:17:24 +00002018
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002019 if len(updatedFlows) >= 0 {
2020 // There are still flows referencing the same flow_id.
2021 // So the flow should not be freed yet.
2022 // For ex: Case of HSIA where same flow is shared
2023 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00002024 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002025 _ = olterrors.NewErrPersistence("update", "flow", flowID,
Shrey Baid26912972020-04-16 21:02:31 +05302026 log.Fields{
2027 "flow": updatedFlows,
2028 "device-id": f.deviceHandler.device.Id}, err).Log()
Girish Kumarf26e4882020-03-05 06:49:10 +00002029 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002030 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05302031 // Do this for subscriber flows only (not trap from NNI flows)
2032 if onuID != -1 && uniID != -1 {
2033 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
2034 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002035 logger.Debugw(ctx, "creating-entry-for-pending-flow-delete",
Shrey Baid26912972020-04-16 21:02:31 +05302036 log.Fields{
2037 "flow-id": flowID,
2038 "intf": Intf,
2039 "onu-id": onuID,
2040 "uni-id": uniID,
2041 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302042 f.pendingFlowDelete.Store(pnFlDelKey, 1)
2043 } else {
2044 pnFlDels := val.(int) + 1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002045 logger.Debugw(ctx, "updating-flow-delete-entry",
Shrey Baid26912972020-04-16 21:02:31 +05302046 log.Fields{
2047 "flow-id": flowID,
2048 "intf": Intf,
2049 "onu-id": onuID,
2050 "uni-id": uniID,
2051 "currPendingFlowCnt": pnFlDels,
2052 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302053 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
2054 }
2055
Neha Sharma96b7bf22020-06-15 10:37:32 +00002056 defer f.deletePendingFlows(ctx, Intf, onuID, uniID)
Girish Gowdra3d633032019-12-10 16:37:05 +05302057 }
2058
Neha Sharma96b7bf22020-06-15 10:37:32 +00002059 logger.Debugw(ctx, "releasing-flow-id-to-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302060 log.Fields{
2061 "Intf": Intf,
2062 "onu-id": onuID,
2063 "uni-id": uniID,
2064 "flow-id": flowID,
2065 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302066 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002067
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002068 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002069 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
2070 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
Shrey Baid26912972020-04-16 21:02:31 +05302071 log.Fields{
2072 "TP-PATH": tpPath,
2073 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302074 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00002075 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +05302076 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
2077 log.Fields{
2078 "tp-id": tpID,
2079 "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002080 }
2081
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302082 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002083 used, err := f.isGemPortUsedByAnotherFlow(ctx, gemPK)
2084 if err != nil {
2085 return err
2086 }
2087 if used {
2088 if f.perGemPortLock.TryLock(gemPK) {
2089 flowIDs := f.flowsUsedByGemPort[gemPK]
2090 for i, flowIDinMap := range flowIDs {
2091 if flowIDinMap == flowID {
2092 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
2093 // everytime flowsUsedByGemPort cache is updated the same should be updated
2094 // in kv store by calling UpdateFlowIDsForGem
2095 f.flowsUsedByGemPort[gemPK] = flowIDs
2096 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs); err != nil {
2097 return err
2098 }
2099 break
Kent Hagermane6ff1012020-07-14 15:07:53 -04002100 }
Gamze Abakafee36392019-10-03 11:17:24 +00002101 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002102 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
2103 log.Fields{
2104 "gemport-id": gemPortID,
2105 "usedByFlows": flowIDs,
2106 "device-id": f.deviceHandler.device.Id})
2107 f.perGemPortLock.Unlock(gemPK)
2108 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00002109 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002110
2111 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
Shrey Baid26912972020-04-16 21:02:31 +05302112 log.Fields{
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002113 "gemport-id": gemPortID,
2114 "device-id": f.deviceHandler.device.Id,
2115 "key": gemPK,
2116 })
2117 return olterrors.NewErrAdapter("failed-to-acquire-per-gem-port-lock", log.Fields{
2118 "gemport-id": gemPortID,
2119 "device-id": f.deviceHandler.device.Id,
2120 "key": gemPK,
2121 }, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00002122 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002123 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05302124 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002125 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
2126 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
npujarec5762e2020-01-01 14:08:48 +05302127 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002128 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002129 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302130 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
2131 // by calling DeleteFlowIDsForGem
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002132 if f.perGemPortLock.TryLock(gemPK) {
2133 delete(f.flowsUsedByGemPort, gemPK)
2134 f.perGemPortLock.Unlock(gemPK)
2135 } else {
2136 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
2137 log.Fields{
2138 "device-id": f.deviceHandler.device.Id,
2139 "key": gemPK,
2140 })
2141 }
npujarec5762e2020-01-01 14:08:48 +05302142 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
2143 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002144 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05302145 // Delete the gem port on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002146 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
2147 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302148 log.Fields{
2149 "err": err,
2150 "intf": Intf,
2151 "onu-id": onuID,
2152 "uni-id": uniID,
2153 "device-id": f.deviceHandler.device.Id,
2154 "gemport-id": gemPortID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302155 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002156 switch techprofileInst := techprofileInst.(type) {
2157 case *tp.TechProfile:
2158 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
2159 if !ok {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002160 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
2161 logger.Warn(ctx, err)
2162 }
2163 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2164 logger.Warn(ctx, err)
2165 }
2166 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 {
2167 logger.Warn(ctx, err)
2168 }
2169 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 {
2170 logger.Warn(ctx, err)
2171 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002172 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
2173 // Delete the TCONT on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002174 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
2175 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002176 log.Fields{
2177 "intf": Intf,
2178 "onu-id": onuID,
2179 "uni-id": uniID,
2180 "device-id": f.deviceHandler.device.Id,
2181 "alloc-id": techprofileInst.UsScheduler.AllocID})
2182 }
2183 }
2184 case *tp.EponProfile:
Kent Hagermane6ff1012020-07-14 15:07:53 -04002185 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
2186 logger.Warn(ctx, err)
2187 }
2188 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2189 logger.Warn(ctx, err)
2190 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002191 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302192 // Delete the TCONT on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002193 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.AllocID), tpPath); err != nil {
2194 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302195 log.Fields{
2196 "intf": Intf,
2197 "onu-id": onuID,
2198 "uni-id": uniID,
2199 "device-id": f.deviceHandler.device.Id,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002200 "alloc-id": techprofileInst.AllocID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302201 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002202 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002203 logger.Errorw(ctx, "error-unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002204 log.Fields{
2205 "techprofileInst": techprofileInst})
Gamze Abakafee36392019-10-03 11:17:24 +00002206 }
2207 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002208 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302209 return nil
2210}
2211
David K. Bainbridge794735f2020-02-11 21:01:37 -08002212// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302213func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302214
Neha Sharma96b7bf22020-06-15 10:37:32 +00002215 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302216 log.Fields{
2217 "flowDirection": flowDirection,
2218 "flow": *flow,
2219 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002220
2221 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05302222 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002223 return
2224 }
2225
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302226 classifierInfo := make(map[string]interface{})
2227
Neha Sharma96b7bf22020-06-15 10:37:32 +00002228 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302229 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002230 logger.Error(ctx, err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302231 return
2232 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302233
David K. Bainbridge794735f2020-02-11 21:01:37 -08002234 onuID := int32(onu)
2235 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302236
2237 for _, field := range flows.GetOfbFields(flow) {
2238 if field.Type == flows.IP_PROTO {
2239 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002240 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302241 }
2242 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002243 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302244 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002245 "flow-id": flow.Id,
2246 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302247 "onu-id": onuID,
2248 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302249
2250 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2251 onuID = -1
2252 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002253 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2254 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002255 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002256 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002257 log.Fields{
2258 "port-number": inPort,
2259 "error": err})
2260 return
2261 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302262 }
npujarec5762e2020-01-01 14:08:48 +05302263 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002264 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302265 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302266 if flowInfo == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002267 logger.Debugw(ctx, "no-flowinfo-found-in-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302268 log.Fields{
2269 "intf": Intf,
2270 "onu-id": onuID,
2271 "uni-id": uniID,
2272 "flow-id": flowID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302273 return
2274 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302275
Kent Hagermane6ff1012020-07-14 15:07:53 -04002276 updatedFlows := *flowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302277 for i, storedFlow := range updatedFlows {
2278 if flow.Id == storedFlow.LogicalFlowID {
2279 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002280 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002281 // DKB
Neha Sharma96b7bf22020-06-15 10:37:32 +00002282 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2283 logger.Errorw(ctx, "failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002284 return
2285 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002286 logger.Info(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002287 "flow-id": flow.Id,
2288 "stored-flow": storedFlow,
2289 "device-id": f.deviceHandler.device.Id,
2290 "stored-flow-id": flowID,
2291 "onu-id": onuID,
2292 "intf": Intf,
2293 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08002294 //Remove the Flow from FlowInfo
2295 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
2296 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
2297 flowID, flowDirection, portNum, updatedFlows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002298 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002299 "flow-id": flow.Id,
2300 "stored-flow": storedFlow,
2301 "device-id": f.deviceHandler.device.Id,
2302 "stored-flow-id": flowID,
2303 "onu-id": onuID,
2304 "intf": Intf,
2305 })
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302306 return
2307 }
2308 }
2309 }
2310 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002311}
2312
Esin Karamanccb714b2019-11-29 15:02:06 +00002313//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
2314// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05302315func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002316 classifierInfo := make(map[string]interface{})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002317 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00002318 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002319
2320 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002321 logger.Warnw(ctx, "no-inport-found--cannot-release-resources-of-the-multicast-flow", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002322 return
2323 }
2324
Esin Karamanccb714b2019-11-29 15:02:06 +00002325 var onuID = int32(NoneOnuID)
2326 var uniID = int32(NoneUniID)
2327 var flowID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00002328
npujarec5762e2020-01-01 14:08:48 +05302329 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002330
2331 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302332 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002333 if flowInfo == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002334 logger.Debugw(ctx, "no-multicast-flowinfo-found-in-the-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302335 log.Fields{
2336 "intf": networkInterfaceID,
2337 "onu-id": onuID,
2338 "uni-id": uniID,
2339 "flow-id": flowID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002340 continue
2341 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002342 updatedFlows := *flowInfo
Esin Karamanccb714b2019-11-29 15:02:06 +00002343 for i, storedFlow := range updatedFlows {
2344 if flow.Id == storedFlow.LogicalFlowID {
2345 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002346 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302347 log.Fields{
2348 "flow": storedFlow,
2349 "flow-id": flow.Id,
2350 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002351 //remove from device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002352 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002353 // DKB
Neha Sharma96b7bf22020-06-15 10:37:32 +00002354 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002355 log.Fields{
2356 "flow-id": flow.Id,
2357 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002358 return
2359 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002360 logger.Infow(ctx, "multicast-flow-removed-from-device-successfully", log.Fields{"flow-id": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002361 //Remove the Flow from FlowInfo
2362 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05302363 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002364 logger.Errorw(ctx, "failed-to-delete-multicast-flow-from-the-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302365 log.Fields{"flow": storedFlow,
2366 "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002367 return
2368 }
2369 //release flow id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002370 logger.Debugw(ctx, "releasing-multicast-flow-id",
Shrey Baid26912972020-04-16 21:02:31 +05302371 log.Fields{"flow-id": flowID,
2372 "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05302373 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002374 }
2375 }
2376 }
2377}
2378
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002379//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002380func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002381 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302382 var direction string
2383 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002384
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302385 for _, action := range flows.GetActions(flow) {
2386 if action.Type == flows.OUTPUT {
2387 if out := action.GetOutput(); out != nil {
2388 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002389 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302390 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002391 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002392 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002393 }
2394 }
2395 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002396
2397 if flows.HasGroup(flow) {
2398 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07002399 f.clearFlowFromResourceManager(ctx, flow, direction)
2400 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002401 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302402 direction = Upstream
2403 } else {
2404 direction = Downstream
2405 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302406
Neha Sharma96b7bf22020-06-15 10:37:32 +00002407 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002408 if err != nil {
2409 return err
2410 }
2411
2412 userKey := tpLockKey{intfID, onuID, uniID}
2413
2414 // Serialize flow removes on a per subscriber basis
2415 if f.perUserFlowHandleLock.TryLock(userKey) {
2416 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
2417 f.perUserFlowHandleLock.Unlock(userKey)
2418 } else {
2419 // Ideally this should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00002420 logger.Errorw(ctx, "failed-to-acquire-lock-to-remove-flow--remove-aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07002421 return errors.New("failed-to-acquire-per-user-lock")
2422 }
2423
2424 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002425}
2426
Girish Gowdra3d633032019-12-10 16:37:05 +05302427func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
2428 uniID uint32, ch chan bool) {
2429 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2430 for {
2431 select {
2432 case <-time.After(20 * time.Millisecond):
2433 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002434 logger.Debug(ctx, "pending-flow-deletes-completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05302435 ch <- true
2436 return
2437 }
2438 case <-ctx.Done():
Neha Sharma96b7bf22020-06-15 10:37:32 +00002439 logger.Error(ctx, "flow-delete-wait-handler-routine-canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05302440 return
2441 }
2442 }
2443}
2444
Esin Karamanae41e2b2019-12-17 18:13:13 +00002445//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2446func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2447 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2448 if ethType, ok := classifierInfo[EthType]; ok {
2449 if ethType.(uint32) == IPv4EthType {
2450 if ipProto, ok := classifierInfo[IPProto]; ok {
2451 if ipProto.(uint32) == IgmpProto {
2452 return true
2453 }
2454 }
2455 }
2456 }
2457 }
2458 return false
2459}
2460
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002461// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302462// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002463func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002464 classifierInfo := make(map[string]interface{})
2465 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002466 var UsMeterID uint32
2467 var DsMeterID uint32
2468
Neha Sharma96b7bf22020-06-15 10:37:32 +00002469 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302470 log.Fields{
2471 "flow": flow,
2472 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002473 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002474
Neha Sharma96b7bf22020-06-15 10:37:32 +00002475 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002476 if err != nil {
2477 // Error logging is already done in the called function
2478 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002479 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302480 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002481
Esin Karamanccb714b2019-11-29 15:02:06 +00002482 if flows.HasGroup(flow) {
2483 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002484 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002485 }
2486
manikkaraj k17652a72019-05-06 09:06:36 -04002487 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002488 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002489 if err != nil {
2490 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002491 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002492 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002493
Neha Sharma96b7bf22020-06-15 10:37:32 +00002494 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302495 log.Fields{
2496 "classifierinfo_inport": classifierInfo[InPort],
2497 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002498 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002499
Humera Kouser94d7a842019-08-25 19:04:32 -04002500 if ethType, ok := classifierInfo[EthType]; ok {
2501 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002502 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002503 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002504 }
2505 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002506 if ipProto, ok := classifierInfo[IPProto]; ok {
2507 if ipProto.(uint32) == IPProtoDhcp {
2508 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302509 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002510 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002511 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002512 }
2513 }
2514 }
2515 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002516 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002517 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002518 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002519 }
A R Karthick1f85b802019-10-11 05:06:05 +00002520
npujarec5762e2020-01-01 14:08:48 +05302521 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002522
Neha Sharma96b7bf22020-06-15 10:37:32 +00002523 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002524 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302525 return olterrors.NewErrNotFound("tpid-for-flow",
2526 log.Fields{
2527 "flow": flow,
2528 "intf-id": IntfID,
2529 "onu-id": onuID,
2530 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002531 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002532 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302533 log.Fields{
2534 "tp-id": TpID,
2535 "intf-id": intfID,
2536 "onu-id": onuID,
2537 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002538 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002539 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002540 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002541 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002542 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002543 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002544
2545 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302546
2547 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2548 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002549 logger.Debugw(ctx, "no-pending-flows-found--going-ahead-with-flow-install",
Shrey Baid26912972020-04-16 21:02:31 +05302550 log.Fields{
2551 "intf-id": intfID,
2552 "onu-id": onuID,
2553 "uni-id": uniID})
Andrea Campanellabfe08432020-09-11 17:07:03 +02002554 return f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302555 }
Andrea Campanellabfe08432020-09-11 17:07:03 +02002556 pendingFlowDelComplete := make(chan bool)
2557 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
2558 select {
2559 case <-pendingFlowDelComplete:
2560 logger.Debugw(ctx, "all-pending-flow-deletes-completed",
2561 log.Fields{
2562 "intf-id": intfID,
2563 "onu-id": onuID,
2564 "uni-id": uniID})
2565 return f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
2566 case <-time.After(10 * time.Second):
2567 return olterrors.NewErrTimeout("pending-flow-deletes",
2568 log.Fields{
2569 "intf-id": intfID,
2570 "onu-id": onuID,
2571 "uni-id": uniID}, nil)
2572 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002573}
2574
Esin Karamanccb714b2019-11-29 15:02:06 +00002575// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002576func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002577 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002578 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302579 "classifier-info": classifierInfo,
2580 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002581
Esin Karaman65409d82020-03-18 10:58:18 +00002582 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002583 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002584 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002585 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002586 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
2587 //otherwise, classification is based on ipv4_dst by default.
2588 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
2589 mcastFlowClassificationByEthDst := false
2590
2591 if mcastFlowClassificationByEthDst {
2592 //replace ipDst with ethDst
2593 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
2594 flows.IsMulticastIp(ipv4Dst.(uint32)) {
2595 // replace ipv4_dst classifier with eth_dst
2596 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
2597 delete(classifierInfo, Ipv4Dst)
2598 classifierInfo[EthDst] = multicastMac
Neha Sharma96b7bf22020-06-15 10:37:32 +00002599 logger.Debugw(ctx, "multicast-ip-to-mac-conversion-success",
Shrey Baid26912972020-04-16 21:02:31 +05302600 log.Fields{
2601 "ip:": ipv4Dst.(uint32),
2602 "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002603 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002604 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002605 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002606
David K. Bainbridge794735f2020-02-11 21:01:37 -08002607 onuID := NoneOnuID
2608 uniID := NoneUniID
2609 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00002610
Neha Sharma96b7bf22020-06-15 10:37:32 +00002611 flowStoreCookie := getFlowStoreCookie(ctx, classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302612 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002613 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002614 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002615 }
npujarec5762e2020-01-01 14:08:48 +05302616 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00002617 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302618 return olterrors.NewErrNotFound("multicast-flow-id",
2619 log.Fields{
2620 "interface-id": networkInterfaceID,
2621 "onu-id": onuID,
2622 "uni-id": uniID,
2623 "gem-port-id": gemPortID,
2624 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002625 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002626 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002627 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2628 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002629 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002630 }
2631 groupID := actionInfo[GroupID].(uint32)
2632 multicastFlow := openoltpb2.Flow{
2633 FlowId: flowID,
2634 FlowType: Multicast,
2635 NetworkIntfId: int32(networkInterfaceID),
2636 GroupId: groupID,
2637 Classifier: classifierProto,
2638 Priority: int32(flow.Priority),
2639 Cookie: flow.Cookie}
2640
Kent Hagermane6ff1012020-07-14 15:07:53 -04002641 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002642 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002643 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002644 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002645 //get cached group
Kent Hagermane6ff1012020-07-14 15:07:53 -04002646 if group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002647 //calling groupAdd to set group members after multicast flow creation
Kent Hagermane6ff1012020-07-14 15:07:53 -04002648 if err := f.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002649 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002650 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002651 //cached group can be removed now
2652 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2653 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2654 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002655 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002656
2657 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2658 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2659 int32(onuID),
2660 int32(uniID),
2661 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002662 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002663 }
2664 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002665}
2666
Esin Karaman65409d82020-03-18 10:58:18 +00002667//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2668func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2669 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002670 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002671 if err != nil {
2672 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2673 }
2674 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002675 }
Esin Karaman65409d82020-03-18 10:58:18 +00002676 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302677 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002678 if e == nil && len(nniPorts) > 0 {
2679 return nniPorts[0], nil
2680 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302681 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002682}
2683
2684// AddGroup add or update the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002685func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002686 logger.Infow(ctx, "add-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002687 if group == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002688 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002689 }
2690
2691 groupToOlt := openoltpb2.Group{
2692 GroupId: group.Desc.GroupId,
2693 Command: openoltpb2.Group_SET_MEMBERS,
2694 Action: f.buildGroupAction(),
2695 }
2696
Neha Sharma96b7bf22020-06-15 10:37:32 +00002697 logger.Debugw(ctx, "sending-group-to-device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05302698 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002699 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002700 return olterrors.NewErrAdapter("add-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002701 }
2702 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05302703 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002704 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002705 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002706 logger.Infow(ctx, "add-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002707 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002708}
2709
Esin Karamand519bbf2020-07-01 11:16:03 +00002710// DeleteGroup deletes a group from the device
2711func (f *OpenOltFlowMgr) DeleteGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
2712 logger.Debugw(ctx, "delete-group", log.Fields{"group": group})
2713 if group == nil {
2714 logger.Error(ctx, "unable-to-delete-group--invalid-argument--group-is-nil")
2715 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
2716 }
2717
2718 groupToOlt := openoltpb2.Group{
2719 GroupId: group.Desc.GroupId,
2720 }
2721
2722 logger.Debugw(ctx, "deleting-group-from-device", log.Fields{"groupToOlt": groupToOlt})
2723 _, err := f.deviceHandler.Client.DeleteGroup(ctx, &groupToOlt)
2724 if err != nil {
2725 logger.Errorw(ctx, "delete-group-failed-on-dev", log.Fields{"groupToOlt": groupToOlt, "err": err})
2726 return olterrors.NewErrAdapter("delete-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
2727 }
2728 //remove group from the store
2729 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, group.Desc.GroupId, false); err != nil {
2730 return olterrors.NewErrPersistence("delete", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
2731 }
2732 logger.Debugw(ctx, "delete-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
2733 return nil
2734}
2735
Esin Karamanccb714b2019-11-29 15:02:06 +00002736//buildGroupAction creates and returns a group action
2737func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2738 var actionCmd openoltpb2.ActionCmd
2739 var action openoltpb2.Action
2740 action.Cmd = &actionCmd
2741 //pop outer vlan
2742 action.Cmd.RemoveOuterTag = true
2743 return &action
2744}
2745
2746// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002747func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002748 logger.Infow(ctx, "modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002749 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002750 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002751 }
2752
Neha Sharma96b7bf22020-06-15 10:37:32 +00002753 newGroup := f.buildGroup(ctx, group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002754 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302755 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002756
2757 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002758 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002759 }
2760
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002761 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002762 if groupExists {
2763 // group already exists
Neha Sharma96b7bf22020-06-15 10:37:32 +00002764 current = f.buildGroup(ctx, group.Desc.GroupId, val.Desc.GetBuckets())
2765 logger.Debugw(ctx, "modify-group--group exists",
Shrey Baid26912972020-04-16 21:02:31 +05302766 log.Fields{
2767 "group on the device": val,
2768 "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002769 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002770 current = f.buildGroup(ctx, group.Desc.GroupId, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002771 }
2772
Neha Sharma96b7bf22020-06-15 10:37:32 +00002773 logger.Debugw(ctx, "modify-group--comparing-current-and-new",
Shrey Baid26912972020-04-16 21:02:31 +05302774 log.Fields{
2775 "group on the device": current,
2776 "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002777 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002778 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002779 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002780 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002781
Neha Sharma96b7bf22020-06-15 10:37:32 +00002782 logger.Infow(ctx, "modify-group--differences found", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302783 "membersToBeAdded": membersToBeAdded,
2784 "membersToBeRemoved": membersToBeRemoved,
2785 "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002786
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002787 groupToOlt := openoltpb2.Group{
2788 GroupId: group.Desc.GroupId,
2789 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002790 var errAdd, errRemoved error
Kent Hagermane6ff1012020-07-14 15:07:53 -04002791 if len(membersToBeAdded) > 0 {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002792 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2793 groupToOlt.Members = membersToBeAdded
2794 //execute addMembers
Neha Sharma96b7bf22020-06-15 10:37:32 +00002795 errAdd = f.callGroupAddRemove(ctx, &groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002796 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002797 if len(membersToBeRemoved) > 0 {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002798 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2799 groupToOlt.Members = membersToBeRemoved
2800 //execute removeMembers
Neha Sharma96b7bf22020-06-15 10:37:32 +00002801 errRemoved = f.callGroupAddRemove(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002802 }
2803
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002804 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002805 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302806 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002807 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002808 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002809 logger.Infow(ctx, "modify-group-was-success--storing-group",
Shrey Baid26912972020-04-16 21:02:31 +05302810 log.Fields{
2811 "group": group,
2812 "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002813 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002814 logger.Warnw(ctx, "one-of-the-group-add/remove-operations-failed--cannot-save-group-modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002815 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002816 if errAdd != nil {
2817 return errAdd
2818 }
2819 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002820 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002821 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002822}
2823
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002824//callGroupAddRemove performs add/remove buckets operation for the indicated group
Neha Sharma96b7bf22020-06-15 10:37:32 +00002825func (f *OpenOltFlowMgr) callGroupAddRemove(ctx context.Context, group *openoltpb2.Group) error {
2826 if err := f.performGroupOperation(ctx, group); err != nil {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002827 st, _ := status.FromError(err)
2828 //ignore already exists error code
2829 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002830 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002831 }
2832 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002833 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002834}
2835
2836//findDiff compares group members and finds members which only exists in groups2
2837func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2838 var members []*openoltpb2.GroupMember
2839 for _, bucket := range group2.Members {
2840 if !f.contains(group1.Members, bucket) {
2841 // bucket does not exist and must be added
2842 members = append(members, bucket)
2843 }
2844 }
2845 return members
2846}
2847
2848//contains returns true if the members list contains the given member; false otherwise
2849func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2850 for _, groupMember := range members {
2851 if groupMember.InterfaceId == member.InterfaceId {
2852 return true
2853 }
2854 }
2855 return false
2856}
2857
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002858//performGroupOperation call performGroupOperation operation of openolt proto
Neha Sharma96b7bf22020-06-15 10:37:32 +00002859func (f *OpenOltFlowMgr) performGroupOperation(ctx context.Context, group *openoltpb2.Group) error {
2860 logger.Debugw(ctx, "sending-group-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05302861 log.Fields{
2862 "groupToOlt": group,
2863 "command": group.Command})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002864 _, err := f.deviceHandler.Client.PerformGroupOperation(log.WithSpanFromContext(context.Background(), ctx), group)
Esin Karamanccb714b2019-11-29 15:02:06 +00002865 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002866 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002867 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002868 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002869}
2870
2871//buildGroup build openoltpb2.Group from given group id and bucket list
Neha Sharma96b7bf22020-06-15 10:37:32 +00002872func (f *OpenOltFlowMgr) buildGroup(ctx context.Context, groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
Esin Karamanccb714b2019-11-29 15:02:06 +00002873 group := openoltpb2.Group{
2874 GroupId: groupID}
2875 // create members of the group
Kent Hagermane6ff1012020-07-14 15:07:53 -04002876 for _, ofBucket := range buckets {
2877 member := f.buildMember(ctx, ofBucket)
2878 if member != nil && !f.contains(group.Members, member) {
2879 group.Members = append(group.Members, member)
Esin Karamanccb714b2019-11-29 15:02:06 +00002880 }
2881 }
2882 return &group
2883}
2884
2885//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
Neha Sharma96b7bf22020-06-15 10:37:32 +00002886func (f *OpenOltFlowMgr) buildMember(ctx context.Context, ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
Esin Karamanccb714b2019-11-29 15:02:06 +00002887 var outPort uint32
2888 outPortFound := false
2889 for _, ofAction := range ofBucket.Actions {
2890 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2891 outPort = ofAction.GetOutput().Port
2892 outPortFound = true
2893 }
2894 }
2895
2896 if !outPortFound {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002897 logger.Debugw(ctx, "bucket-skipped-since-no-out-port-found-in-it", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002898 return nil
2899 }
2900 interfaceID := IntfIDFromUniPortNum(outPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002901 logger.Debugw(ctx, "got-associated-interface-id-of-the-port",
Shrey Baid26912972020-04-16 21:02:31 +05302902 log.Fields{
2903 "portNumber:": outPort,
2904 "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002905 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2906 member := openoltpb2.GroupMember{
2907 InterfaceId: interfaceID,
2908 InterfaceType: openoltpb2.GroupMember_PON,
2909 GemPortId: groupInfo.gemPortID,
2910 Priority: groupInfo.servicePriority,
2911 }
2912 //add member to the group
2913 return &member
2914 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002915 logger.Warnf(ctx, "bucket-skipped-since-interface-2-gem-mapping-cannot-be-found", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002916 return nil
2917}
2918
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002919//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002920func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002921
Neha Sharma96b7bf22020-06-15 10:37:32 +00002922 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302923 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002924 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302925 log.Fields{
2926 "intf-id": intfID,
2927 "onu-id": onuID,
2928 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002929 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302930 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002931 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002932
Neha Sharma96b7bf22020-06-15 10:37:32 +00002933 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002934 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002935 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002936 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002937 tpDownloadMsg,
2938 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302939 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002940 onuDev.deviceType,
2941 onuDev.deviceID,
2942 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002943 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302944 return olterrors.NewErrCommunication("send-techprofile-download-request",
2945 log.Fields{
2946 "from-adapter": f.deviceHandler.device.Type,
2947 "to-adapter": onuDev.deviceType,
2948 "onu-id": onuDev.deviceID,
2949 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002950 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002951 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302952 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302953}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002954
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302955//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002956func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302957
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002958 f.onuGemInfoLock.Lock()
2959 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002960
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302961 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2962 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002963 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002964 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302965 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002966 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302967 log.Fields{
2968 "intf-id": intfID,
2969 "onu-id": onuID,
2970 "serial-num": serialNum,
2971 "onu": onu,
2972 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002973 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002974}
2975
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302976//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302977func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002978
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002979 f.onuGemInfoLock.Lock()
2980 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002981
Neha Sharma96b7bf22020-06-15 10:37:32 +00002982 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302983 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002984 "gem-port-id": gemPort,
2985 "intf-id": intfID,
2986 "onu-id": onuID,
2987 "device-id": f.deviceHandler.device.Id,
2988 "onu-gem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302989 onugem := f.onuGemInfo[intfID]
2990 // update the gem to the local cache as well as to kv strore
2991 for idx, onu := range onugem {
2992 if onu.OnuID == onuID {
2993 // check if gem already exists , else update the cache and kvstore
2994 for _, gem := range onu.GemPorts {
2995 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002996 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302997 log.Fields{
2998 "gem": gemPort,
2999 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303000 return
3001 }
3002 }
3003 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
3004 f.onuGemInfo[intfID] = onugem
3005 }
3006 }
npujarec5762e2020-01-01 14:08:48 +05303007 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303008 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003009 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05303010 log.Fields{
3011 "intf-id": intfID,
3012 "onu-id": onuID,
3013 "gemPort": gemPort,
3014 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003015 return
3016 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003017 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05303018 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003019 "gem-port-id": gemPort,
3020 "intf-id": intfID,
3021 "onu-id": onuID,
3022 "device-id": f.deviceHandler.device.Id,
3023 "onu-gem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003024}
3025
3026// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003027
3028//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 +00003029func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303030
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003031 f.onuGemInfoLock.RLock()
3032 defer f.onuGemInfoLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303033
Neha Sharma96b7bf22020-06-15 10:37:32 +00003034 logger.Infow(ctx, "getting-onu-id-from-gem-port-and-pon-port",
Shrey Baid26912972020-04-16 21:02:31 +05303035 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003036 "device-id": f.deviceHandler.device.Id,
3037 "onu-geminfo": f.onuGemInfo[intfID],
3038 "intf-id": intfID,
3039 "gemport-id": gemPortID})
Matteo Scandolod625b4c2020-04-02 16:16:01 -07003040
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303041 // get onuid from the onugem info cache
3042 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07003043
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303044 for _, onu := range onugem {
3045 for _, gem := range onu.GemPorts {
3046 if gem == gemPortID {
3047 return onu.OnuID, nil
3048 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003049 }
3050 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003051 logger.Errorw(ctx, "onu-id-from-gem-port-not-found", log.Fields{
3052 "gem-port-id": gemPortID,
3053 "interface-id": intfID,
Kent Hagermane6ff1012020-07-14 15:07:53 -04003054 "all-gems-on-port": onugem,
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003055 })
Thomas Lee S94109f12020-03-03 16:39:29 +05303056 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003057 "interface-id": intfID,
3058 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00003059 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003060}
3061
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003062//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05303063func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003064 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003065 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003066 var err error
3067
3068 if packetIn.IntfType == "pon" {
3069 // packet indication does not have serial number , so sending as nil
Neha Sharma96b7bf22020-06-15 10:37:32 +00003070 if onuID, err = f.getOnuIDfromGemPortMap(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003071 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003072 return logicalPortNum, err
3073 }
3074 if packetIn.PortNo != 0 {
3075 logicalPortNum = packetIn.PortNo
3076 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003077 uniID := uint32(0) // FIXME - multi-uni support
Neha Sharma96b7bf22020-06-15 10:37:32 +00003078 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003079 }
3080 // 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 +00003081 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003082 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003083 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003084 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003085 logger.Infow(ctx, "retrieved-logicalport-from-packet-in",
Shrey Baid26912972020-04-16 21:02:31 +05303086 log.Fields{
3087 "logical-port-num": logicalPortNum,
3088 "intf-type": packetIn.IntfType,
3089 "packet": hex.EncodeToString(packetIn.Pkt),
3090 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003091 return logicalPortNum, nil
3092}
3093
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003094//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00003095func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003096 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00003097
3098 ctag, priority, err := getCTagFromPacket(ctx, packet)
3099 if err != nil {
3100 return 0, err
3101 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303102
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003103 f.onuGemInfoLock.RLock()
3104 defer f.onuGemInfoLock.RUnlock()
Esin Karaman7fb80c22020-07-16 14:23:33 +00003105 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003106 var ok bool
3107 gemPortID, ok = f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303108 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003109 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05303110 log.Fields{
3111 "pktinkey": pktInkey,
3112 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003113
3114 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003115 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303116 //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 +00003117 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303118 if err == nil {
3119 if gemPortID != 0 {
3120 f.packetInGemPort[pktInkey] = gemPortID
Neha Sharma96b7bf22020-06-15 10:37:32 +00003121 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05303122 log.Fields{
3123 "pktinkey": pktInkey,
3124 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303125 return gemPortID, nil
3126 }
3127 }
Shrey Baid26912972020-04-16 21:02:31 +05303128 return uint32(0), olterrors.NewErrNotFound("gem-port",
3129 log.Fields{
3130 "pktinkey": pktInkey,
3131 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003132
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003133}
3134
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003135// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303136func installFlowOnAllGemports(ctx context.Context,
3137 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003138 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003139 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05303140 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303141 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303142 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003143 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003144 args map[string]uint32,
3145 classifier map[string]interface{}, action map[string]interface{},
3146 logicalFlow *ofp.OfpFlowStats,
3147 gemPorts []uint32,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003148 TpInst interface{},
Manikkaraj kb1d51442019-07-23 10:41:02 -04003149 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00003150 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003151 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003152 vlanID ...uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003153 logger.Debugw(ctx, "installing-flow-on-all-gem-ports",
Shrey Baid26912972020-04-16 21:02:31 +05303154 log.Fields{
3155 "FlowType": FlowType,
3156 "gemPorts": gemPorts,
3157 "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05303158
Gamze Abaka724d0852020-03-18 12:10:24 +00003159 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
3160 // We need to trim prefix "0b", before further processing
3161 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
3162 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
3163
3164 // If a particular character in the string is set to '1', identify the index of this character from
3165 // the LSB position which marks the PCP bit consumed by the given gem port.
3166 // This PCP bit now becomes a classifier in the flow.
3167
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003168 switch TpInst := TpInst.(type) {
3169 case *tp.TechProfile:
3170 attributes := TpInst.DownstreamGemPortAttributeList
3171 if direction == Upstream {
3172 attributes = TpInst.UpstreamGemPortAttributeList
Gamze Abaka724d0852020-03-18 12:10:24 +00003173 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003174
3175 for _, gemPortAttribute := range attributes {
3176 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
3177 continue
Gamze Abaka724d0852020-03-18 12:10:24 +00003178 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003179 gemPortID := gemPortAttribute.GemportID
3180 if allPbitsMarked(gemPortAttribute.PbitMap) {
3181 classifier[VlanPcp] = uint32(VlanPCPMask)
3182 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003183 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3184 logger.Warn(ctx, err)
3185 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003186 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003187 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3188 logger.Warn(ctx, err)
3189 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003190 }
3191 } else {
3192 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
3193 if pbitSet == BinaryBit1 {
3194 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3195 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003196 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3197 logger.Warn(ctx, err)
3198 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003199 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003200 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3201 logger.Warn(ctx, err)
3202 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003203 }
3204 }
3205 }
3206 }
3207 }
3208 case *tp.EponProfile:
3209 if direction == Upstream {
3210 attributes := TpInst.UpstreamQueueAttributeList
3211 for _, queueAttribute := range attributes {
3212 gemPortID := queueAttribute.GemportID
3213 if allPbitsMarked(queueAttribute.PbitMap) {
3214 classifier[VlanPcp] = uint32(VlanPCPMask)
Gamze Abaka724d0852020-03-18 12:10:24 +00003215 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003216 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3217 logger.Warn(ctx, err)
3218 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003219 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003220 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3221 logger.Warn(ctx, err)
3222 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003223 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003224 } else {
3225 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3226 if pbitSet == BinaryBit1 {
3227 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3228 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003229 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3230 logger.Warn(ctx, err)
3231 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003232 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003233 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3234 logger.Warn(ctx, err)
3235 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003236 }
3237 }
3238 }
3239 }
3240 }
3241 } else {
3242 attributes := TpInst.DownstreamQueueAttributeList
3243 for _, queueAttribute := range attributes {
3244 gemPortID := queueAttribute.GemportID
3245 if allPbitsMarked(queueAttribute.PbitMap) {
3246 classifier[VlanPcp] = uint32(VlanPCPMask)
3247 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003248 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3249 logger.Warn(ctx, err)
3250 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003251 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003252 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3253 logger.Warn(ctx, err)
3254 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003255 }
3256 } else {
3257 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3258 if pbitSet == BinaryBit1 {
3259 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3260 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003261 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3262 logger.Warn(ctx, err)
3263 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003264 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003265 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3266 logger.Warn(ctx, err)
3267 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003268 }
3269 }
3270 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05303271 }
3272 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04003273 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003274 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003275 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpInst": TpInst})
Manikkaraj kb1d51442019-07-23 10:41:02 -04003276 }
3277}
3278
Gamze Abaka724d0852020-03-18 12:10:24 +00003279func allPbitsMarked(pbitMap string) bool {
3280 for pos, pBit := range pbitMap {
3281 if pos >= 2 && pBit != BinaryBit1 {
3282 return false
3283 }
3284 }
3285 return true
3286}
3287
David K. Bainbridge794735f2020-02-11 21:01:37 -08003288func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003289 logger.Debug(ctx, "adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003290 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003291 classifier[PacketTagType] = DoubleTag
3292 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003293 /* We manage flowId resource pool on per PON port basis.
3294 Since this situation is tricky, as a hack, we pass the NNI port
3295 index (network_intf_id) as PON port Index for the flowId resource
3296 pool. Also, there is no ONU Id available for trapping DHCP packets
3297 on NNI port, use onu_id as -1 (invalid)
3298 ****************** CAVEAT *******************
3299 This logic works if the NNI Port Id falls within the same valid
3300 range of PON Port Ids. If this doesn't work for some OLT Vendor
3301 we need to have a re-look at this.
3302 *********************************************
3303 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003304 onuID := -1
3305 uniID := -1
3306 gemPortID := -1
3307 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00003308 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303309 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303310 return olterrors.NewErrNotFound("nni-intreface-id",
3311 log.Fields{
3312 "classifier": classifier,
3313 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003314 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303315 }
3316
Neha Sharma96b7bf22020-06-15 10:37:32 +00003317 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303318 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003319 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003320 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003321 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003322 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003323 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303324 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id",
3325 log.Fields{
3326 "interface-id": networkInterfaceID,
3327 "onu-id": onuID,
3328 "uni-id": uniID,
3329 "gem-port-id": gemPortID,
3330 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003331 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003332 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003333 classifierProto, err := makeOpenOltClassifierField(classifier)
3334 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003335 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003336 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003337 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003338 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003339 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003340 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003341 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003342 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003343 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3344 OnuId: int32(onuID), // OnuId not required
3345 UniId: int32(uniID), // UniId not used
3346 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07003347 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003348 AllocId: int32(allocID), // AllocId not used
3349 NetworkIntfId: int32(networkInterfaceID),
3350 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003351 Classifier: classifierProto,
3352 Action: actionProto,
3353 Priority: int32(logicalFlow.Priority),
3354 Cookie: logicalFlow.Cookie,
3355 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003356 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003357 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003358 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003359 logger.Info(ctx, "dhcp-trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003360 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3361 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3362 int32(onuID),
3363 int32(uniID),
3364 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003365 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003366 }
3367 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003368}
salmansiddiqui7ac62132019-08-22 03:58:50 +00003369
Esin Karamanae41e2b2019-12-17 18:13:13 +00003370//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
3371func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
3372 var packetType string
3373 ovid, ivid := false, false
3374 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
3375 vid := vlanID & VlanvIDMask
3376 if vid != ReservedVlan {
3377 ovid = true
3378 }
3379 }
3380 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
3381 vid := uint32(metadata)
3382 if vid != ReservedVlan {
3383 ivid = true
3384 }
3385 }
3386 if ovid && ivid {
3387 packetType = DoubleTag
3388 } else if !ovid && !ivid {
3389 packetType = Untagged
3390 } else {
3391 packetType = SingleTag
3392 }
3393 return packetType
3394}
3395
3396//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08003397func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003398 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003399 action := make(map[string]interface{})
3400 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
3401 action[TrapToHost] = true
3402 /* We manage flowId resource pool on per PON port basis.
3403 Since this situation is tricky, as a hack, we pass the NNI port
3404 index (network_intf_id) as PON port Index for the flowId resource
3405 pool. Also, there is no ONU Id available for trapping packets
3406 on NNI port, use onu_id as -1 (invalid)
3407 ****************** CAVEAT *******************
3408 This logic works if the NNI Port Id falls within the same valid
3409 range of PON Port Ids. If this doesn't work for some OLT Vendor
3410 we need to have a re-look at this.
3411 *********************************************
3412 */
3413 onuID := -1
3414 uniID := -1
3415 gemPortID := -1
3416 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00003417 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003418 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303419 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003420 "classifier": classifier,
3421 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003422 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003423 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003424 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303425 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003426 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003427 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003428 }
npujarec5762e2020-01-01 14:08:48 +05303429 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003430 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303431 return olterrors.NewErrNotFound("igmp-flow-id",
3432 log.Fields{
3433 "interface-id": networkInterfaceID,
3434 "onu-id": onuID,
3435 "uni-id": uniID,
3436 "gem-port-id": gemPortID,
3437 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003438 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003439 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003440 classifierProto, err := makeOpenOltClassifierField(classifier)
3441 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003442 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003443 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003444 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003445 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003446 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003447 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003448 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003449 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003450 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3451 OnuId: int32(onuID), // OnuId not required
3452 UniId: int32(uniID), // UniId not used
3453 FlowId: flowID,
3454 FlowType: Downstream,
3455 AllocId: int32(allocID), // AllocId not used
3456 NetworkIntfId: int32(networkInterfaceID),
3457 GemportId: int32(gemPortID), // GemportId not used
3458 Classifier: classifierProto,
3459 Action: actionProto,
3460 Priority: int32(logicalFlow.Priority),
3461 Cookie: logicalFlow.Cookie,
3462 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003463 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003464 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003465 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003466 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003467 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3468 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3469 int32(onuID),
3470 int32(uniID),
3471 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003472 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003473 }
3474 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003475}
3476
salmansiddiqui7ac62132019-08-22 03:58:50 +00003477func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
3478 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05303479 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003480 }
3481 if Dir == tp_pb.Direction_UPSTREAM {
3482 return "upstream", nil
3483 } else if Dir == tp_pb.Direction_DOWNSTREAM {
3484 return "downstream", nil
3485 }
3486 return "", nil
3487}
3488
Kent Hagermane6ff1012020-07-14 15:07:53 -04003489// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303490func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003491 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003492 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00003493 var gemPort uint32
3494 intfID := args[IntfID]
3495 onuID := args[OnuID]
3496 uniID := args[UniID]
3497 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003498 allocID := args[AllocID]
salmansiddiqui7ac62132019-08-22 03:58:50 +00003499 if ipProto, ok := classifierInfo[IPProto]; ok {
3500 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003501 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003502 "tp-id": tpID,
3503 "alloc-id": allocID,
3504 "intf-id": intfID,
3505 "onu-id": onuID,
3506 "uni-id": uniID,
3507 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003508 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003509 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003510 tp_pb.Direction_UPSTREAM,
3511 pcp.(uint32))
3512 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00003513
Kent Hagermane6ff1012020-07-14 15:07:53 -04003514 if err := f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3515 logger.Warn(ctx, err)
3516 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003517 } else {
3518 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003519 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003520 }
3521
Girish Gowdra32625212020-04-29 11:26:35 -07003522 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003523 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05303524 log.Fields{
3525 "intf-id": intfID,
3526 "onu-id": onuID,
3527 "uni-id": uniID,
3528 "classifier-info:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003529 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003530 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
Esin Karamanae41e2b2019-12-17 18:13:13 +00003531 tp_pb.Direction_UPSTREAM,
3532 pcp.(uint32))
Kent Hagermane6ff1012020-07-14 15:07:53 -04003533 if err := f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3534 logger.Warn(ctx, err)
3535 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00003536 } else {
3537 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003538 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003539 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003540 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003541 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003542 return
3543 }
3544 } else if ethType, ok := classifierInfo[EthType]; ok {
3545 if ethType.(uint32) == EapEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003546 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003547 "intf-id": intfID,
3548 "onu-id": onuID,
3549 "uni-id": uniID,
3550 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003551 var vlanID uint32
3552 if val, ok := classifierInfo[VlanVid]; ok {
3553 vlanID = (val.(uint32)) & VlanvIDMask
3554 } else {
3555 vlanID = DefaultMgmtVlan
3556 }
3557 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003558 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003559 tp_pb.Direction_UPSTREAM,
3560 pcp.(uint32))
3561
Kent Hagermane6ff1012020-07-14 15:07:53 -04003562 if err := f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID); err != nil {
3563 logger.Warn(ctx, err)
3564 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003565 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003566 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003567 }
3568 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003569 } else if _, ok := actionInfo[PushVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003570 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003571 "intf-id": intfID,
3572 "onu-id": onuID,
3573 "uni-id": uniID,
3574 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003575 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003576 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003577 tp_pb.Direction_UPSTREAM,
3578 pcp.(uint32))
3579 //Adding HSIA upstream flow
Kent Hagermane6ff1012020-07-14 15:07:53 -04003580 if err := f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3581 logger.Warn(ctx, err)
3582 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003583 } else {
3584 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003585 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003586 }
3587 } else if _, ok := actionInfo[PopVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003588 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003589 "intf-id": intfID,
3590 "onu-id": onuID,
3591 "uni-id": uniID,
3592 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003593 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003594 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05003595 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003596 pcp.(uint32))
3597 //Adding HSIA downstream flow
Kent Hagermane6ff1012020-07-14 15:07:53 -04003598 if err := f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3599 logger.Warn(ctx, err)
3600 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003601 } else {
3602 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003603 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003604 }
3605 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003606 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05303607 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003608 "intf-id": intfID,
3609 "onu-id": onuID,
3610 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05303611 "classifier": classifierInfo,
3612 "action": actionInfo,
3613 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003614 return
3615 }
3616 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04003617 go func() {
3618 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
3619 logger.Warn(ctx, err)
3620 }
3621 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003622}
3623
Matteo Scandolo738c52a2020-08-03 11:14:22 -07003624func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(ctx context.Context, gemPK gemPortKey) (bool, error) {
3625 if f.perGemPortLock.TryLock(gemPK) {
3626 flowIDList := f.flowsUsedByGemPort[gemPK]
3627 f.perGemPortLock.Unlock(gemPK)
3628 return len(flowIDList) > 1, nil
3629 }
3630 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
3631 log.Fields{
3632 "device-id": f.deviceHandler.device.Id,
3633 "key": gemPK,
3634 })
3635 return false, olterrors.NewErrAdapter("failed-to-acquire-per-gem-port-lock", log.Fields{
3636 "device-id": f.deviceHandler.device.Id,
3637 "key": gemPK,
3638 }, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003639}
3640
npujarec5762e2020-01-01 14:08:48 +05303641func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3642 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003643 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3644 for _, currentGemPort := range currentGemPorts {
3645 for _, tpGemPort := range tpGemPorts {
3646 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3647 return true, currentGemPort
3648 }
3649 }
3650 }
Girish Gowdra54934262019-11-13 14:19:55 +05303651 if tpInst.InstanceCtrl.Onu == "single-instance" {
3652 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Kent Hagermane6ff1012020-07-14 15:07:53 -04003653 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID); err != nil {
3654 logger.Warn(ctx, err)
3655 }
3656 if err := f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
3657 logger.Warn(ctx, err)
3658 }
Girish Gowdra54934262019-11-13 14:19:55 +05303659
3660 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3661 // still be used on other uni ports.
3662 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3663 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003664 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003665 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303666 for i := 0; i < len(tpInstances); i++ {
3667 tpI := tpInstances[i]
3668 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303669 for _, tpGemPort := range tpGemPorts {
3670 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003671 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303672 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303673 }
3674 }
3675 }
3676 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003677 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003678 return false, 0
3679}
3680
Neha Sharma96b7bf22020-06-15 10:37:32 +00003681func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003682 for _, field := range flows.GetOfbFields(flow) {
3683 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003684 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003685 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003686 } else if field.Type == flows.ETH_DST {
3687 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003688 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003689 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003690 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003691 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003692 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003693 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003694 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003695 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303696 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003697 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003698 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003699 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003700 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003701 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003702 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003703 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003704 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003705 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003706 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003707 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003708 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003709 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003710 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003711 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003712 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003713 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003714 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003715 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003716 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003717 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003718 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003719 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003720 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003721 return
3722 }
3723 }
3724}
3725
Neha Sharma96b7bf22020-06-15 10:37:32 +00003726func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003727 for _, action := range flows.GetActions(flow) {
3728 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003729 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003730 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003731 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003732 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003733 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003734 }
Scott Baker355d1742019-10-24 10:57:52 -07003735 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003736 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003737 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003738 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003739 if out := action.GetPush(); out != nil {
3740 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003741 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003742 } else {
3743 actionInfo[PushVlan] = true
3744 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003745 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303746 log.Fields{
3747 "push-tpid": actionInfo[TPID].(uint32),
3748 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003749 }
3750 }
Scott Baker355d1742019-10-24 10:57:52 -07003751 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003752 if out := action.GetSetField(); out != nil {
3753 if field := out.GetField(); field != nil {
3754 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003755 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003756 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003757 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3758 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003759 }
3760 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003761 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003762 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003763 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003764 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003765 }
3766 }
3767 return nil
3768}
3769
Neha Sharma96b7bf22020-06-15 10:37:32 +00003770func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003771 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003772 fieldtype := ofbField.GetType()
3773 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003774 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3775 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003776 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003777 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003778 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003779 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003780 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3781 pcp := ofbField.GetVlanPcp()
3782 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003783 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003784 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003785 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003786 }
3787 }
3788}
3789
Neha Sharma96b7bf22020-06-15 10:37:32 +00003790func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003791 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003792 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003793 } else {
3794 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003795 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003796 }
3797}
3798
Neha Sharma96b7bf22020-06-15 10:37:32 +00003799func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003800 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003801 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003802 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3803 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003804 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003805 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003806 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303807 log.Fields{
3808 "newinport": classifierInfo[InPort].(uint32),
3809 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003810 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303811 return olterrors.NewErrNotFound("child-in-port",
3812 log.Fields{
3813 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3814 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003815 }
3816 }
3817 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003818 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003819 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003820 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003821 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003822 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003823 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303824 log.Fields{
3825 "newoutport": actionInfo[Output].(uint32),
3826 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003827 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303828 return olterrors.NewErrNotFound("out-port",
3829 log.Fields{
3830 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3831 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003832 }
3833 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3834 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003835 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003836 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003837 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303838 log.Fields{
3839 "newinport": actionInfo[Output].(uint32),
3840 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003841 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303842 return olterrors.NewErrNotFound("nni-port",
3843 log.Fields{
3844 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3845 "in-port": classifierInfo[InPort].(uint32),
3846 "out-port": actionInfo[Output].(uint32),
3847 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003848 }
3849 }
3850 }
3851 return nil
3852}
Gamze Abakafee36392019-10-03 11:17:24 +00003853
Neha Sharma96b7bf22020-06-15 10:37:32 +00003854func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003855 /* Metadata 8 bytes:
3856 Most Significant 2 Bytes = Inner VLAN
3857 Next 2 Bytes = Tech Profile ID(TPID)
3858 Least Significant 4 Bytes = Port ID
3859 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3860 subscriber related flows.
3861 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003862 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003863 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003864 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003865 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003866 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003867 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003868}
3869
3870func appendUnique(slice []uint32, item uint32) []uint32 {
3871 for _, sliceElement := range slice {
3872 if sliceElement == item {
3873 return slice
3874 }
3875 }
3876 return append(slice, item)
3877}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303878
3879// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003880func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303881
3882 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3883 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003884 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003885 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003886 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003887 log.Fields{
3888 "port-number": action[Output].(uint32),
3889 "error": err})
3890 return uint32(0), err
3891 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003892 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303893 return intfID, nil
3894 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003895 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003896 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003897 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003898 log.Fields{
3899 "port-number": action[Output].(uint32),
3900 "error": err})
3901 return uint32(0), err
3902 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003903 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303904 return intfID, nil
3905 }
3906 return uint32(0), nil
3907}
3908
3909// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003910func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3911 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3912 if err != nil {
3913 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3914 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3915 return
3916 }
3917 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003918
3919 f.onuGemInfoLock.Lock()
3920 defer f.onuGemInfoLock.Unlock()
3921
Matt Jeanneret1719a072019-12-20 14:50:14 -05003922 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303923 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003924 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003925 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 +05303926 log.Fields{
3927 "pktinkey": pktInkey,
3928 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003929 return
3930 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303931 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003932 f.packetInGemPort[pktInkey] = gemPort
3933
npujarec5762e2020-01-01 14:08:48 +05303934 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003935 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 +05303936 log.Fields{
3937 "pktinkey": pktInkey,
3938 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303939}
3940
Esin Karaman7fb80c22020-07-16 14:23:33 +00003941//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3942func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3943 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003944 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003945 return 0, 0, errors.New("invalid packet length")
3946 }
3947 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3948 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3949
3950 var index int8
3951 if outerEthType == 0x8100 {
3952 if innerEthType == 0x8100 {
3953 // q-in-q 802.1ad or 802.1q double tagged packet.
3954 // get the inner vlanId
3955 index = 18
3956 } else {
3957 index = 14
3958 }
3959 priority := (packet[index] >> 5) & 0x7
3960 //13 bits composes vlanId value
3961 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3962 return vlan, priority, nil
3963 }
3964 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3965 return 0, 0, nil
3966}
3967
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303968// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303969func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003970
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003971 f.onuGemInfoLock.Lock()
3972 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003973
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303974 onugem := f.onuGemInfo[intfID]
3975 for idx, onu := range onugem {
3976 if onu.OnuID == onuID {
3977 for _, uni := range onu.UniPorts {
3978 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003979 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 +05303980 return
3981 }
3982 }
3983 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3984 f.onuGemInfo[intfID] = onugem
3985 }
3986 }
npujarec5762e2020-01-01 14:08:48 +05303987 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003988
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303989}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303990
npujarec5762e2020-01-01 14:08:48 +05303991func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3992 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303993 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003994 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303995 return
3996 }
3997 for gem, FlowIDs := range flowIDsList {
3998 gemPK := gemPortKey{intf, uint32(gem)}
Matteo Scandolo738c52a2020-08-03 11:14:22 -07003999 if f.perGemPortLock.TryLock(gemPK) {
4000 f.flowsUsedByGemPort[gemPK] = FlowIDs
4001 f.perGemPortLock.Unlock(gemPK)
4002 } else {
4003 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
4004 log.Fields{
4005 "intf-id": intf,
4006 "device-id": f.deviceHandler.device.Id,
4007 "key": gemPK,
4008 })
4009 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05304010 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05304011}
Esin Karamanccb714b2019-11-29 15:02:06 +00004012
4013//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
4014//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05304015func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
4016 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00004017 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00004018 logger.Error(ctx, "failed-to-get-pon-interface-to-multicast-queue-map")
Esin Karamanccb714b2019-11-29 15:02:06 +00004019 return
4020 }
4021 for intf, queueInfo := range storedMulticastQueueMap {
4022 q := queueInfoBrief{
4023 gemPortID: queueInfo[0],
4024 servicePriority: queueInfo[1],
4025 }
4026 f.interfaceToMcastQueueMap[intf] = &q
4027 }
4028}
4029
4030//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
4031//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
4032//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05304033func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
4034 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00004035 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00004036 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00004037 }
4038 if exists {
4039 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
4040 }
4041 return nil, exists, nil
4042}
4043
4044func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
4045 groupDesc := ofp.OfpGroupDesc{
4046 Type: ofp.OfpGroupType_OFPGT_ALL,
4047 GroupId: groupID,
4048 }
4049 groupEntry := ofp.OfpGroupEntry{
4050 Desc: &groupDesc,
4051 }
Esin Karamanccb714b2019-11-29 15:02:06 +00004052 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00004053 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00004054 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00004055 bucket := ofp.OfpBucket{
4056 Actions: acts,
4057 }
4058 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00004059 }
Esin Karamanccb714b2019-11-29 15:02:06 +00004060 return &groupEntry
4061}