blob: 709735a6e8f280660ddee079e3a698b3becbed61 [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)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530257 //Load the onugem info cache from kv store on flowmanager start
258 for idx = 0; idx < ponPorts; idx++ {
npujarec5762e2020-01-01 14:08:48 +0530259 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000260 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530261 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530262 //Load flowID list per gem map per interface from the kvstore.
npujarec5762e2020-01-01 14:08:48 +0530263 flowMgr.loadFlowIDlistForGem(ctx, idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530264 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700265 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdra3d633032019-12-10 16:37:05 +0530266 flowMgr.pendingFlowDelete = sync.Map{}
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700267 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(maxRetry, maxDelay, baseDelay, factor, jitter)
268 flowMgr.perGemPortLock = mapmutex.NewCustomizedMapMutex(maxRetry, maxDelay, baseDelay, factor, jitter)
Esin Karamanccb714b2019-11-29 15:02:06 +0000269 flowMgr.interfaceToMcastQueueMap = make(map[uint32]*queueInfoBrief)
270 //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,
310 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
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 {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000330 logger.Errorw(ctx, "no-onu-id-for-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530331 log.Fields{
332 "port-no": portNo,
333 "classifer": classifierInfo,
334 "action": actionInfo,
335 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530336 return
337 }
338
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700339 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000340 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530341 "uni": uni,
342 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530343
344 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
345 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000346 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530347 "device-id": f.deviceHandler.device.Id,
348 "intf-id": intfID,
349 "onu-id": onuID,
350 "uni-id": uniID,
351 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700352 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530353 "action": actionInfo,
354 "usmeter-id": UsMeterID,
355 "dsmeter-id": DsMeterID,
356 "tp-id": TpID})
npujarec5762e2020-01-01 14:08:48 +0530357 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530358 if allocID == 0 || gemPorts == nil || TpInst == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000359 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530360 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
361 return
362 }
363 args := make(map[string]uint32)
364 args[IntfID] = intfID
365 args[OnuID] = onuID
366 args[UniID] = uniID
367 args[PortNo] = portNo
368 args[AllocID] = allocID
369
370 /* Flows can be added specific to gemport if p-bits are received.
371 * If no pbit mentioned then adding flows for all gemports
372 */
npujarec5762e2020-01-01 14:08:48 +0530373 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530374 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
375 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000376 logger.Errorw(ctx, "failed-to-acquire-per-user-flow-handle-lock",
Shrey Baid26912972020-04-16 21:02:31 +0530377 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700378 "intf-id": intfID,
379 "onu-id": onuID,
380 "uni-id": uniID,
381 "flow-id": flow.Id,
382 "flow-cookie": flow.Cookie,
383 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400384 return
385 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530386}
387
salmansiddiqui7ac62132019-08-22 03:58:50 +0000388// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530389func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400390
Neha Sharma96b7bf22020-06-15 10:37:32 +0000391 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530392 log.Fields{"dir": sq.direction,
393 "intf-id": sq.intfID,
394 "onu-id": sq.onuID,
395 "uni-id": sq.uniID,
396 "tp-id": sq.tpID,
397 "meter-id": sq.meterID,
398 "tp-inst": sq.tpInst,
399 "flowmetadata": sq.flowMetadata,
400 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401
Gamze Abakafee36392019-10-03 11:17:24 +0000402 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000403 if err != nil {
404 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400405 }
406
407 /* Lets make a simple assumption that if the meter-id is present on the KV store,
408 * then the scheduler and queues configuration is applied on the OLT device
409 * in the given direction.
410 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000411
Manikkaraj kb1d51442019-07-23 10:41:02 -0400412 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530413 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400414 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530415 return olterrors.NewErrNotFound("meter",
416 log.Fields{"intf-id": sq.intfID,
417 "onu-id": sq.onuID,
418 "uni-id": sq.uniID,
419 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400420 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000421
Manikkaraj kb1d51442019-07-23 10:41:02 -0400422 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000423 if KvStoreMeter.MeterId == sq.meterID {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000424 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400425 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400426 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530427 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800428 "unsupported": "meter-id",
429 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530430 "meter-id-in-flow": sq.meterID,
431 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000433
Neha Sharma96b7bf22020-06-15 10:37:32 +0000434 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530435 log.Fields{
436 "meter-id": sq.meterID,
437 "direction": Direction,
438 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000439
Gamze Abakafee36392019-10-03 11:17:24 +0000440 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000441 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000442 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000443 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400444 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000445
446 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530447 return olterrors.NewErrNotFound("scheduler-config",
448 log.Fields{
449 "intf-id": sq.intfID,
450 "direction": sq.direction,
451 "tp-inst": sq.tpInst,
452 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000453 }
454
Manikkaraj kb1d51442019-07-23 10:41:02 -0400455 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000456 if sq.flowMetadata != nil {
457 for _, meter := range sq.flowMetadata.Meters {
458 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400459 meterConfig = meter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000460 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Shrey Baid26912972020-04-16 21:02:31 +0530461 log.Fields{"meterConfig": meterConfig,
462 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400463 break
464 }
465 }
466 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000467 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400468 }
469 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530470 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800471 "reason": "Could-not-get-meterbands-from-flowMetadata",
472 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530473 "meter-id": sq.meterID,
474 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400475 } else if len(meterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000476 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Shrey Baid26912972020-04-16 21:02:31 +0530477 log.Fields{"Bands": meterConfig.Bands,
478 "meter-id": sq.meterID,
479 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530480 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800481 "reason": "Invalid-number-of-bands-in-meter",
482 "meterband-count": len(meterConfig.Bands),
483 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530484 "meter-id": sq.meterID,
485 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400486 }
487 cir := meterConfig.Bands[0].Rate
488 cbs := meterConfig.Bands[0].BurstSize
489 eir := meterConfig.Bands[1].Rate
490 ebs := meterConfig.Bands[1].BurstSize
491 pir := cir + eir
492 pbs := cbs + ebs
493 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
494
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700495 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000496 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400497
npujarec5762e2020-01-01 14:08:48 +0530498 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530499 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
500 log.Fields{"intf-id": sq.intfID,
501 "direction": sq.direction,
502 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503 }
504
salmansiddiqui7ac62132019-08-22 03:58:50 +0000505 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400506 * store the meter id on the KV store, for further reference.
507 */
npujarec5762e2020-01-01 14:08:48 +0530508 if err := f.resourceMgr.UpdateMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530509 return olterrors.NewErrAdapter("failed-updating-meter-id",
510 log.Fields{"onu-id": sq.onuID,
511 "meter-id": sq.meterID,
512 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400513 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000514 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530515 log.Fields{"direction": Direction,
516 "Meter": meterConfig,
517 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400518 return nil
519}
520
npujarec5762e2020-01-01 14:08:48 +0530521func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000522 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000523
524 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530525 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
526 log.Fields{"intf-id": sq.intfID,
527 "direction": sq.direction,
528 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000529 }
530
Neha Sharma96b7bf22020-06-15 10:37:32 +0000531 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530532 log.Fields{
533 "direction": sq.direction,
534 "TrafficScheds": TrafficSched,
535 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530536 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000537 IntfId: sq.intfID, OnuId: sq.onuID,
538 UniId: sq.uniID, PortNo: sq.uniPort,
539 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000540 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000541 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000542 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530543 "direction": sq.direction,
544 "traffic-queues": trafficQueues,
545 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000546
547 // On receiving the CreateTrafficQueues request, the driver should create corresponding
548 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000549 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530550 log.Fields{"direction": sq.direction,
551 "traffic-queues": trafficQueues,
552 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530553 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000554 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
555 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000556 TrafficQueues: trafficQueues,
557 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530558 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000559 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000560 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530561 "direction": sq.direction,
562 "traffic-queues": trafficQueues,
563 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000564
Esin Karamanccb714b2019-11-29 15:02:06 +0000565 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000566 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000567 if len(multicastTrafficQueues) > 0 {
568 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
569 //assumed that there is only one queue per PON for the multicast service
570 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
571 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000572 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000573 multicastQueuePerPonPort := multicastTrafficQueues[0]
574 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
575 gemPortID: multicastQueuePerPonPort.GemportId,
576 servicePriority: multicastQueuePerPonPort.Priority,
577 }
578 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400579 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
580 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
581 return err
582 }
Shrey Baid26912972020-04-16 21:02:31 +0530583
Neha Sharma96b7bf22020-06-15 10:37:32 +0000584 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000585 }
586 }
587 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000588 return nil
589}
590
salmansiddiqui7ac62132019-08-22 03:58:50 +0000591// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530592func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400593
594 var Direction string
595 var SchedCfg *tp_pb.SchedulerConfig
596 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000597 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530598 log.Fields{
599 "direction": sq.direction,
600 "intf-id": sq.intfID,
601 "onu-id": sq.onuID,
602 "uni-id": sq.uniID,
603 "uni-port": sq.uniPort,
604 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000605 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000606 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400607 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000608 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000609 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400610 Direction = "downstream"
611 }
612
Girish Kumar8f73fe02019-12-09 13:19:37 +0000613 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530614 return olterrors.NewErrNotFound("scheduler-config",
615 log.Fields{
616 "int-id": sq.intfID,
617 "direction": sq.direction,
618 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000619 }
620
npujarec5762e2020-01-01 14:08:48 +0530621 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400622 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530623 return olterrors.NewErrNotFound("meter",
624 log.Fields{
625 "onu-id": sq.onuID,
626 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400627 }
628 if KVStoreMeter == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000629 logger.Warnw(ctx, "no-meter-installed-yet",
Shrey Baid26912972020-04-16 21:02:31 +0530630 log.Fields{
631 "direction": Direction,
632 "intf-id": sq.intfID,
633 "onu-id": sq.onuID,
634 "uni-id": sq.uniID,
635 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400636 return nil
637 }
638 cir := KVStoreMeter.Bands[0].Rate
639 cbs := KVStoreMeter.Bands[0].BurstSize
640 eir := KVStoreMeter.Bands[1].Rate
641 ebs := KVStoreMeter.Bands[1].BurstSize
642 pir := cir + eir
643 pbs := cbs + ebs
644
645 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
646
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700647 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000648 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000649
Neha Sharma96b7bf22020-06-15 10:37:32 +0000650 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000651 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530652 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
653 log.Fields{
654 "intf-id": sq.intfID,
655 "direction": sq.direction,
656 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000657 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400658
npujarec5762e2020-01-01 14:08:48 +0530659 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000660 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
661 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000662 TrafficQueues: TrafficQueues,
663 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000664 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530665 log.Fields{
666 "intf-id": sq.intfID,
667 "traffic-queues": TrafficQueues,
668 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400669 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000670 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530671 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000672 IntfId: sq.intfID, OnuId: sq.onuID,
673 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400674 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000675 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530676 log.Fields{
677 "intf-id": sq.intfID,
678 "traffic-schedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400679 }
680
Neha Sharma96b7bf22020-06-15 10:37:32 +0000681 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000682
683 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400684 * delete the meter id on the KV store.
685 */
npujarec5762e2020-01-01 14:08:48 +0530686 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400687 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530688 return olterrors.NewErrAdapter("unable-to-remove-meter",
689 log.Fields{
690 "onu": sq.onuID,
691 "meter": KVStoreMeter.MeterId,
692 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400693 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000694 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530695 log.Fields{
696 "meter-id": KVStoreMeter.MeterId,
697 "dir": Direction,
698 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400699 return err
700}
701
Gamze Abakafee36392019-10-03 11:17:24 +0000702// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700703func (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 +0000704 var allocIDs []uint32
705 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530706 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530707 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000708 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000709
npujarec5762e2020-01-01 14:08:48 +0530710 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
711 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400712
Neha Sharma96b7bf22020-06-15 10:37:32 +0000713 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530714
Neha Sharma96b7bf22020-06-15 10:37:32 +0000715 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530716 "intf-id": intfID,
717 "onu-id": onuID,
718 "uni-id": uniID,
719 "device-id": f.deviceHandler.device.Id,
720 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530721
Manikkaraj kb1d51442019-07-23 10:41:02 -0400722 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530723 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000724 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000725 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530726 log.Fields{
727 "path": tpPath,
728 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530729 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000730 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530731 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000732 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530733 log.Fields{
734 "error": err,
735 "tp-id": TpID,
736 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000737 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530738 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400739 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
740 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
741 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530742 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000743 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530744 log.Fields{
745 "uni": uni,
746 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530747 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530748 }
Gamze Abakafee36392019-10-03 11:17:24 +0000749
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700750 switch tpInst := techProfileInstance.(type) {
751 case *tp.TechProfile:
752 if UsMeterID != 0 {
753 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
754 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
755 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000756 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700757 log.Fields{
758 "error": err,
759 "meter-id": UsMeterID,
760 "device-id": f.deviceHandler.device.Id})
761 return 0, nil, nil
762 }
763 }
764 if DsMeterID != 0 {
765 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
766 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
767 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000768 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700769 log.Fields{
770 "error": err,
771 "meter-id": DsMeterID,
772 "device-id": f.deviceHandler.device.Id})
773 return 0, nil, nil
774 }
775 }
776 allocID := tpInst.UsScheduler.AllocID
777 for _, gem := range tpInst.UpstreamGemPortAttributeList {
778 gemPortIDs = append(gemPortIDs, gem.GemportID)
779 }
780 allocIDs = appendUnique(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000781
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700782 if tpInstanceExists {
783 return allocID, gemPortIDs, techProfileInstance
784 }
785
786 for _, gemPortID := range gemPortIDs {
787 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
788 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000789 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700790 log.Fields{
791 "alloc-ids": allocIDs,
792 "gemports": allgemPortIDs,
793 "device-id": f.deviceHandler.device.Id})
794 // Send Tconts and GEM ports to KV store
795 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530796 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700797 case *tp.EponProfile:
798 // CreateSchedulerQueues for EPON needs to be implemented here
799 // when voltha-protos for EPON is completed.
800 allocID := tpInst.AllocID
801 for _, gem := range tpInst.UpstreamQueueAttributeList {
802 gemPortIDs = append(gemPortIDs, gem.GemportID)
803 }
804 allocIDs = appendUnique(allocIDs, allocID)
805
806 if tpInstanceExists {
807 return allocID, gemPortIDs, techProfileInstance
808 }
809
810 for _, gemPortID := range gemPortIDs {
811 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
812 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000813 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700814 log.Fields{
815 "alloc-ids": allocIDs,
816 "gemports": allgemPortIDs,
817 "device-id": f.deviceHandler.device.Id})
818 // Send Tconts and GEM ports to KV store
819 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
820 return allocID, gemPortIDs, techProfileInstance
821 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000822 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700823 log.Fields{
824 "tpInst": tpInst})
825 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530826 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530827}
828
npujarec5762e2020-01-01 14:08:48 +0530829func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530830
Neha Sharma96b7bf22020-06-15 10:37:32 +0000831 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530832 log.Fields{
833 "intf-id": intfID,
834 "onu-id": onuID,
835 "uni-id": uniID,
836 "alloc-id": allocID,
837 "gemport-ids": gemPortIDs,
838 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530839 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530840 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000841 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 +0530842 }
npujarec5762e2020-01-01 14:08:48 +0530843 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000844 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 +0530845 }
npujarec5762e2020-01-01 14:08:48 +0530846 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000847 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 +0530848 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000849 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 -0400850 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530851 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400852 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530853}
854
Neha Sharma96b7bf22020-06-15 10:37:32 +0000855func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000856 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530857 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000858 for _, intfID := range techRange.IntfIds {
859 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400860 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000861 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530862 log.Fields{
863 "intf-id": intfID,
864 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530865 }
866 }
867 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400868 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530869 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530870 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800871 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530872 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
873 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530874 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000875 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530876 log.Fields{
877 "numofTech": tpCount,
878 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
879 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530880 return nil
881}
882
npujarec5762e2020-01-01 14:08:48 +0530883func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530884 portNo uint32, uplinkClassifier map[string]interface{},
885 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000886 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700887 uplinkClassifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000888 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530889 log.Fields{
890 "uplinkClassifier": uplinkClassifier,
891 "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800892 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000893 Upstream, logicalFlow, allocID, gemportID, tpID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530894 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530895}
896
npujarec5762e2020-01-01 14:08:48 +0530897func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530898 portNo uint32, downlinkClassifier map[string]interface{},
899 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000900 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700901 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000902 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530903 log.Fields{
904 "downlinkClassifier": downlinkClassifier,
905 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400906 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
907 if vlan, exists := downlinkClassifier[VlanVid]; exists {
908 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700909 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Neha Sharma96b7bf22020-06-15 10:37:32 +0000910 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, intfID, onuID, uniID) {
911 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530912 log.Fields{
913 "flow": logicalFlow,
914 "device-id": f.deviceHandler.device.Id,
915 "onu-id": onuID,
916 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800917 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400918 }
919 }
920 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530921 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400922
Manikkaraj k884c1242019-04-11 16:26:42 +0530923 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700924 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400925 // vlan_vid is a uint32. must be type asserted as such or conversion fails
926 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530927 if ok {
928 downlinkAction[VlanVid] = dlClVid & 0xfff
929 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530930 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530931 "reason": "failed-to-convert-vlanid-classifier",
932 "vlan-id": VlanVid,
933 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530934 }
935
David K. Bainbridge794735f2020-02-11 21:01:37 -0800936 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000937 Downstream, logicalFlow, allocID, gemportID, tpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530938}
939
npujarec5762e2020-01-01 14:08:48 +0530940func (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 +0530941 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000942 allocID uint32, gemPortID uint32, tpID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530943 /* One of the OLT platform (Broadcom BAL) requires that symmetric
944 flows require the same flow_id to be used across UL and DL.
945 Since HSIA flow is the only symmetric flow currently, we need to
946 re-use the flow_id across both direction. The 'flow_category'
947 takes priority over flow_cookie to find any available HSIA_FLOW
948 id for the ONU.
949 */
Neha Sharma96b7bf22020-06-15 10:37:32 +0000950 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530951 log.Fields{
952 "intf-id": intfID,
953 "onu-id": onuID,
954 "uni-id": uniID,
955 "device-id": f.deviceHandler.device.Id,
956 "classifier": classifier,
957 "action": action,
958 "direction": direction,
959 "alloc-id": allocID,
960 "gemport-id": gemPortID,
961 "logicalflow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530962 var vlanPbit uint32 = 0xff // means no pbit
Gamze Abaka724d0852020-03-18 12:10:24 +0000963 var vlanVid uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400964 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000965 vlanPbit = classifier[VlanPcp].(uint32)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000966 logger.Debugw(ctx, "found-pbit-in-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530967 log.Fields{
968 "vlan-pbit": vlanPbit,
969 "intf-id": intfID,
970 "onu-id": onuID,
971 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800972 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000973 logger.Debugw(ctx, "pbit-not-found-in-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530974 log.Fields{
975 "vlan-pcp": VlanPcp,
976 "intf-id": intfID,
977 "onu-id": onuID,
978 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400979 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000980 if _, ok := classifier[VlanVid]; ok {
981 vlanVid = classifier[VlanVid].(uint32)
Shrey Baid26912972020-04-16 21:02:31 +0530982 log.Debugw("found-vlan-in-the-flow",
983 log.Fields{
984 "vlan-vid": vlanVid,
985 "intf-id": intfID,
986 "onu-id": onuID,
987 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000988 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000989 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530990 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000991 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +0530992 log.Fields{
993 "device-id": f.deviceHandler.device.Id,
994 "intf-id": intfID,
995 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800996 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530997 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000998 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530999 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301000 return olterrors.NewErrNotFound("hsia-flow-id",
1001 log.Fields{
1002 "direction": direction,
1003 "device-id": f.deviceHandler.device.Id,
1004 "intf-id": intfID,
1005 "onu-id": onuID,
1006 }, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301007 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001008 classifierProto, err := makeOpenOltClassifierField(classifier)
1009 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301010 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301011 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001012 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301013 log.Fields{
1014 "classifier": *classifierProto,
1015 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001016 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001017 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301018 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301019 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001020 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301021 log.Fields{
1022 "action": *actionProto,
1023 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001024 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301025 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301026 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001027 log.Fields{
1028 "classifier": classifier,
1029 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301030 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001031 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301032 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001033 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
1034 OnuId: int32(onuID),
1035 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +00001036 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +05301037 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001038 AllocId: int32(allocID),
1039 NetworkIntfId: int32(networkIntfID),
1040 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +05301041 Classifier: classifierProto,
1042 Action: actionProto,
1043 Priority: int32(logicalFlow.Priority),
1044 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001045 PortNo: portNo,
1046 TechProfileId: tpID,
1047 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001048 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301049 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301050 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001051 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301052 log.Fields{"direction": direction,
1053 "device-id": f.deviceHandler.device.Id,
1054 "flow": flow,
1055 "intf-id": intfID,
1056 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001057 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
1058 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1059 flow.OnuId,
1060 flow.UniId,
1061 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301062 return olterrors.NewErrPersistence("update", "flow", flowID,
1063 log.Fields{
1064 "flow": flow,
1065 "device-id": f.deviceHandler.device.Id,
1066 "intf-id": intfID,
1067 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001068 }
1069 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301070}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001071
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001072func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1073 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1074 gemPortID uint32, tpID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301075
Neha Sharma96b7bf22020-06-15 10:37:32 +00001076 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301077 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301078 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001079 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301080 "action": action,
1081 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001082 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301083 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301084
1085 // Clear the action map
1086 for k := range action {
1087 delete(action, k)
1088 }
1089
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001090 action[TrapToHost] = true
1091 classifier[UDPSrc] = uint32(68)
1092 classifier[UDPDst] = uint32(67)
1093 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301094
Neha Sharma96b7bf22020-06-15 10:37:32 +00001095 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301096 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001097 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301098 log.Fields{
1099 "device-id": f.deviceHandler.device.Id,
1100 "intf-id": intfID,
1101 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001102 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301103 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301104
David K. Bainbridge794735f2020-02-11 21:01:37 -08001105 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 +05301106
1107 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301108 return olterrors.NewErrNotFound("flow",
1109 log.Fields{
1110 "interface-id": intfID,
1111 "gem-port": gemPortID,
1112 "cookie": flowStoreCookie,
1113 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001114 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301115 }
1116
Neha Sharma96b7bf22020-06-15 10:37:32 +00001117 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301118 log.Fields{
1119 "ul_classifier": classifier,
1120 "ul_action": action,
1121 "uplinkFlowId": flowID,
1122 "intf-id": intfID,
1123 "onu-id": onuID,
1124 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301125
David K. Bainbridge794735f2020-02-11 21:01:37 -08001126 classifierProto, err := makeOpenOltClassifierField(classifier)
1127 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301128 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301129 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001130 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001131 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001132 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301133 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301134 }
1135
David K. Bainbridge794735f2020-02-11 21:01:37 -08001136 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001137 OnuId: int32(onuID),
1138 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301139 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001140 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001141 AllocId: int32(allocID),
1142 NetworkIntfId: int32(networkIntfID),
1143 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301144 Classifier: classifierProto,
1145 Action: actionProto,
1146 Priority: int32(logicalFlow.Priority),
1147 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001148 PortNo: portNo,
1149 TechProfileId: tpID,
1150 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001151 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301152 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001153 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001154 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301155 log.Fields{
1156 "device-id": f.deviceHandler.device.Id,
1157 "flow-id": flowID,
1158 "intf-id": intfID,
1159 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001160 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
1161 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
1162 dhcpFlow.OnuId,
1163 dhcpFlow.UniId,
1164 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301165 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1166 log.Fields{
1167 "flow": dhcpFlow,
1168 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301169 }
1170
David K. Bainbridge794735f2020-02-11 21:01:37 -08001171 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301172}
1173
Esin Karamanae41e2b2019-12-17 18:13:13 +00001174//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301175func (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 +00001176 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32) error {
1177 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001178}
1179
1180//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301181func (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 +00001182 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string, tpID uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001183
Neha Sharma96b7bf22020-06-15 10:37:32 +00001184 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001185 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301186 return olterrors.NewErrNotFound("nni-interface-id",
1187 log.Fields{
1188 "classifier": classifier,
1189 "action": action,
1190 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001191 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001192 }
1193
1194 // Clear the action map
1195 for k := range action {
1196 delete(action, k)
1197 }
1198
1199 action[TrapToHost] = true
1200 classifier[PacketTagType] = SingleTag
1201 delete(classifier, VlanVid)
1202
Neha Sharma96b7bf22020-06-15 10:37:32 +00001203 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301204 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001205 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001206 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001207 }
1208
npujarec5762e2020-01-01 14:08:48 +05301209 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 +00001210
1211 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301212 return olterrors.NewErrNotFound("flow-id",
1213 log.Fields{
1214 "intf-id": intfID,
1215 "oni-id": onuID,
1216 "cookie": flowStoreCookie,
1217 "flow-type": flowType,
1218 "device-id": f.deviceHandler.device.Id,
1219 "onu-id": onuID},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001220 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001221 }
1222
Neha Sharma96b7bf22020-06-15 10:37:32 +00001223 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301224 log.Fields{
1225 "ul_classifier": classifier,
1226 "ul_action": action,
1227 "uplinkFlowId": flowID,
1228 "flowType": flowType,
1229 "device-id": f.deviceHandler.device.Id,
1230 "intf-id": intfID,
1231 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001232
David K. Bainbridge794735f2020-02-11 21:01:37 -08001233 classifierProto, err := makeOpenOltClassifierField(classifier)
1234 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301235 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001236 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001237 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301238 log.Fields{
1239 "classifier": *classifierProto,
1240 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001241 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001242 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301243 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001244 }
1245
David K. Bainbridge794735f2020-02-11 21:01:37 -08001246 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001247 OnuId: int32(onuID),
1248 UniId: int32(uniID),
1249 FlowId: flowID,
1250 FlowType: Upstream,
1251 AllocId: int32(allocID),
1252 NetworkIntfId: int32(networkIntfID),
1253 GemportId: int32(gemPortID),
1254 Classifier: classifierProto,
1255 Action: actionProto,
1256 Priority: int32(logicalFlow.Priority),
1257 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001258 PortNo: portNo,
1259 TechProfileId: tpID,
1260 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001261
David K. Bainbridge794735f2020-02-11 21:01:37 -08001262 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301263 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 -08001264 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001265 logger.Infof(ctx, "%s ul-flow-added-to-device-successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001266
David K. Bainbridge794735f2020-02-11 21:01:37 -08001267 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
1268 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1269 flow.OnuId,
1270 flow.UniId,
1271 flow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301272 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 +00001273 }
1274
David K. Bainbridge794735f2020-02-11 21:01:37 -08001275 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001276}
1277
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001278// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001279func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1280 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1281 gemPortID uint32, vlanID uint32, tpID uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001282 logger.Infow(ctx, "adding-eapol-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301283 log.Fields{
1284 "intf-id": intfID,
1285 "onu-id": onuID,
1286 "port-no": portNo,
1287 "alloc-id": allocID,
1288 "gemport-id": gemPortID,
1289 "vlan-id": vlanID,
1290 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301291
1292 uplinkClassifier := make(map[string]interface{})
1293 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301294
manikkaraj kbf256be2019-03-25 00:13:48 +05301295 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001296 uplinkClassifier[EthType] = uint32(EapEthType)
1297 uplinkClassifier[PacketTagType] = SingleTag
1298 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001299 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301300 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001301 uplinkAction[TrapToHost] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00001302 flowStoreCookie := getFlowStoreCookie(ctx, uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301303 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001304 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301305 "device-id": f.deviceHandler.device.Id,
1306 "onu-id": onuID,
1307 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001308 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301309 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301310 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +00001311 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +05301312 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301313 return olterrors.NewErrNotFound("flow-id",
1314 log.Fields{
1315 "intf-id": intfID,
1316 "onu-id": onuID,
1317 "coookie": flowStoreCookie,
1318 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001319 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301320 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001321 logger.Debugw(ctx, "creating-ul-eapol-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301322 log.Fields{
1323 "ul_classifier": uplinkClassifier,
1324 "ul_action": uplinkAction,
1325 "uplinkFlowId": uplinkFlowID,
1326 "device-id": f.deviceHandler.device.Id,
1327 "intf-id": intfID,
1328 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301329
David K. Bainbridge794735f2020-02-11 21:01:37 -08001330 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1331 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301332 return olterrors.NewErrInvalidValue(log.Fields{
1333 "classifier": uplinkClassifier,
1334 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301335 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001336 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301337 log.Fields{
1338 "classifier": *classifierProto,
1339 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001340 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001341 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301342 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301343 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001344 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301345 log.Fields{
1346 "action": *actionProto,
1347 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001348 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301349 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301350 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001351 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301352 "action": action,
1353 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001354 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301355 }
1356
David K. Bainbridge794735f2020-02-11 21:01:37 -08001357 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001358 OnuId: int32(onuID),
1359 UniId: int32(uniID),
1360 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001361 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001362 AllocId: int32(allocID),
1363 NetworkIntfId: int32(networkIntfID),
1364 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301365 Classifier: classifierProto,
1366 Action: actionProto,
1367 Priority: int32(logicalFlow.Priority),
1368 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001369 PortNo: portNo,
1370 TechProfileId: tpID,
1371 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001372 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301373 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001374 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001375 logger.Infow(ctx, "eapol-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301376 log.Fields{
1377 "device-id": f.deviceHandler.device.Id,
1378 "onu-id": onuID,
1379 "intf-id": intfID,
1380 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001381 flowCategory := "EAPOL"
1382 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1383 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1384 upstreamFlow.OnuId,
1385 upstreamFlow.UniId,
1386 upstreamFlow.FlowId,
1387 /* lowCategory, */
1388 flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301389 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1390 log.Fields{
1391 "flow": upstreamFlow,
1392 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301393 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001394 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301395}
1396
David K. Bainbridge794735f2020-02-11 21:01:37 -08001397func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001398 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001399
1400 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1401 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1402 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001403 if vlanID != ReservedVlan {
1404 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001405 classifier.OVid = vid
1406 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301407 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001408 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1409 vid := uint32(metadata)
1410 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001411 classifier.IVid = vid
1412 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301413 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301414 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001415 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301416 classifier.OPbits = vlanPcp
1417 } else {
1418 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301419 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001420 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1421 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1422 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1423 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001424 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001425 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1426 classifier.PktTagType = pktTagType
1427
1428 switch pktTagType {
1429 case SingleTag:
1430 case DoubleTag:
1431 case Untagged:
1432 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001433 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301434 }
1435 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001436 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301437}
1438
Gamze Abaka724d0852020-03-18 12:10:24 +00001439func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001440 var actionCmd openoltpb2.ActionCmd
1441 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301442 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001443 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301444 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001445 if _, ok := actionInfo[VlanPcp]; ok {
1446 action.Cmd.RemarkInnerPbits = true
1447 action.IPbits = actionInfo[VlanPcp].(uint32)
1448 if _, ok := actionInfo[VlanVid]; ok {
1449 action.Cmd.TranslateInnerTag = true
1450 action.IVid = actionInfo[VlanVid].(uint32)
1451 }
1452 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001453 } else if _, ok := actionInfo[PushVlan]; ok {
1454 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301455 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001456 if _, ok := actionInfo[VlanPcp]; ok {
1457 action.OPbits = actionInfo[VlanPcp].(uint32)
1458 action.Cmd.RemarkOuterPbits = true
1459 if _, ok := classifierInfo[VlanVid]; ok {
1460 action.IVid = classifierInfo[VlanVid].(uint32)
1461 action.Cmd.TranslateInnerTag = true
1462 }
1463 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001464 } else if _, ok := actionInfo[TrapToHost]; ok {
1465 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301466 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001467 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301468 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001469 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301470}
1471
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001472// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001473func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1474 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301475}
1476
Gamze Abakafee36392019-10-03 11:17:24 +00001477// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301478func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1479 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001480 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1481
Gamze Abakafee36392019-10-03 11:17:24 +00001482 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301483 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001484 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301485 // return err
1486 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001487 }
Shrey Baid26912972020-04-16 21:02:31 +05301488 log.Debugw("tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001489 }
1490 return nil
1491}
1492
1493// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301494func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001495 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001496 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001497 }
npujarec5762e2020-01-01 14:08:48 +05301498 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301499 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1500 log.Fields{
1501 "tp-id": tpID,
1502 "uni-port-name": uniPortName,
1503 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001504 }
1505 return nil
1506}
1507
Neha Sharma96b7bf22020-06-15 10:37:32 +00001508func getFlowStoreCookie(ctx context.Context, classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301509 if len(classifier) == 0 { // should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00001510 logger.Error(ctx, "invalid-classfier-object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301511 return 0
1512 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001513 logger.Debugw(ctx, "generating-flow-store-cookie",
Shrey Baid26912972020-04-16 21:02:31 +05301514 log.Fields{
1515 "classifier": classifier,
1516 "gemport-id": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301517 var jsonData []byte
1518 var flowString string
1519 var err error
1520 // TODO: Do we need to marshall ??
1521 if jsonData, err = json.Marshal(classifier); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001522 logger.Error(ctx, "failed-to-encode-classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301523 return 0
1524 }
1525 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001526 if gemPortID != 0 {
1527 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301528 }
1529 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001530 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301531 hash := big.NewInt(0)
1532 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301533 generatedHash := hash.Uint64()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001534 logger.Debugw(ctx, "hash-generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301535 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301536}
1537
npujarec5762e2020-01-01 14:08:48 +05301538func (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 +05301539 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001540 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001541 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1542 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1543 */
1544 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001545 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001546 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001547 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001548 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001549 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301550 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001551 if existingFlows != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001552 logger.Debugw(ctx, "flow-exists-for-given-flowID--appending-it-to-current-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301553 log.Fields{
1554 "flow-id": flow.FlowId,
1555 "device-id": f.deviceHandler.device.Id,
1556 "intf-id": intfID,
1557 "onu-id": flow.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001558 //for _, f := range *existingFlows {
1559 // flows = append(flows, f)
1560 //}
1561 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001562 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001563 logger.Debugw(ctx, "updated-flows-for-given-flowID-and-onuid",
Shrey Baid26912972020-04-16 21:02:31 +05301564 log.Fields{
1565 "updatedflow": flows,
1566 "flow-id": flow.FlowId,
1567 "onu-id": flow.OnuId,
1568 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +05301569 return &flows
1570}
1571
npujarec5762e2020-01-01 14:08:48 +05301572func (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 +00001573 logger.Debugw(ctx, "storing-flow(s)-into-kv-store", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301574 "flow-id": flowID,
1575 "device-id": f.deviceHandler.device.Id,
1576 "intf-id": intfID,
1577 "onu-id": onuID})
npujarec5762e2020-01-01 14:08:48 +05301578 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001579 logger.Warnw(ctx, "error-while-storing-flow-into-kv-store", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301580 "device-id": f.deviceHandler.device.Id,
1581 "onu-id": onuID,
1582 "intf-id": intfID,
1583 "flow-id": flowID})
manikkaraj k17652a72019-05-06 09:06:36 -04001584 return err
1585 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001586 logger.Infow(ctx, "stored-flow(s)-into-kv-store-successfully!", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301587 "device-id": f.deviceHandler.device.Id,
1588 "onu-id": onuID,
1589 "intf-id": intfID,
1590 "flow-id": flowID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301591 return nil
1592}
1593
David K. Bainbridge794735f2020-02-11 21:01:37 -08001594func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001595
1596 var intfID uint32
1597 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1598 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1599 */
1600 if deviceFlow.AccessIntfId != -1 {
1601 intfID = uint32(deviceFlow.AccessIntfId)
1602 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001603 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001604 intfID = uint32(deviceFlow.NetworkIntfId)
1605 }
1606
Neha Sharma96b7bf22020-06-15 10:37:32 +00001607 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301608 "flow": *deviceFlow,
1609 "device-id": f.deviceHandler.device.Id,
1610 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001611 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001612
1613 st, _ := status.FromError(err)
1614 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001615 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001616 "err": err,
1617 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301618 "device-id": f.deviceHandler.device.Id,
1619 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001620 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301621 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001622
1623 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001624 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301625 log.Fields{"err": err,
1626 "device-flow": deviceFlow,
1627 "device-id": f.deviceHandler.device.Id,
1628 "intf-id": intfID})
npujarec5762e2020-01-01 14:08:48 +05301629 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001630 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001631 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301632 if deviceFlow.GemportId != -1 {
1633 // No need to register the flow if it is a trap on nni flow.
Kent Hagermane6ff1012020-07-14 15:07:53 -04001634 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1635 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1636 return err
1637 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301638 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001639 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301640 log.Fields{
1641 "flow": *deviceFlow,
1642 "device-id": f.deviceHandler.device.Id,
1643 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001644 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001645}
1646
Neha Sharma96b7bf22020-06-15 10:37:32 +00001647func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1648 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301649 log.Fields{
1650 "flow": *deviceFlow,
1651 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001652 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001653 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001654 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001655 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301656 log.Fields{
1657 "err": err,
1658 "deviceFlow": deviceFlow,
1659 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001660 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001661 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001662 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001663 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001664
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001665 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001666 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001667 "of-flow-id": ofFlowID,
1668 "flow": *deviceFlow,
1669 "device-id": f.deviceHandler.device.Id,
1670 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001671 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301672}
1673
David K. Bainbridge794735f2020-02-11 21:01:37 -08001674func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001675
1676 classifierInfo := make(map[string]interface{})
1677 actionInfo := make(map[string]interface{})
1678
1679 classifierInfo[EthType] = uint32(LldpEthType)
1680 classifierInfo[PacketTagType] = Untagged
1681 actionInfo[TrapToHost] = true
1682
1683 // LLDP flow is installed to trap LLDP packets on the NNI port.
1684 // We manage flow_id resource pool on per PON port basis.
1685 // Since this situation is tricky, as a hack, we pass the NNI port
1686 // index (network_intf_id) as PON port Index for the flow_id resource
1687 // pool. Also, there is no ONU Id available for trapping LLDP packets
1688 // on NNI port, use onu_id as -1 (invalid)
1689 // ****************** CAVEAT *******************
1690 // This logic works if the NNI Port Id falls within the same valid
1691 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1692 // we need to have a re-look at this.
1693 // *********************************************
1694
1695 var onuID = -1
1696 var uniID = -1
1697 var gemPortID = -1
1698
Neha Sharma96b7bf22020-06-15 10:37:32 +00001699 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001700 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301701 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001702 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001703 var flowStoreCookie = getFlowStoreCookie(ctx, classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301704 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001705 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001706 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001707 }
npujarec5762e2020-01-01 14:08:48 +05301708 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001709
1710 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301711 return olterrors.NewErrNotFound("flow-id",
1712 log.Fields{
1713 "interface-id": networkInterfaceID,
1714 "onu-id": onuID,
1715 "uni-id": uniID,
1716 "gem-port-id": gemPortID,
1717 "cookie": flowStoreCookie,
1718 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001719 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001720 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001721 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1722 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301723 return olterrors.NewErrInvalidValue(
1724 log.Fields{
1725 "classifier": classifierInfo,
1726 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001727 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001728 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301729 log.Fields{
1730 "classifier": *classifierProto,
1731 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001732 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001733 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301734 return olterrors.NewErrInvalidValue(
1735 log.Fields{
1736 "action": actionInfo,
1737 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001738 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001739 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301740 log.Fields{
1741 "action": *actionProto,
1742 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001743
1744 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1745 OnuId: int32(onuID), // OnuId not required
1746 UniId: int32(uniID), // UniId not used
1747 FlowId: flowID,
1748 FlowType: Downstream,
1749 NetworkIntfId: int32(networkInterfaceID),
1750 GemportId: int32(gemPortID),
1751 Classifier: classifierProto,
1752 Action: actionProto,
1753 Priority: int32(flow.Priority),
1754 Cookie: flow.Cookie,
1755 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001756 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301757 return olterrors.NewErrFlowOp("add", flowID,
1758 log.Fields{
1759 "flow": downstreamflow,
1760 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001761 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001762 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301763 log.Fields{
1764 "device-id": f.deviceHandler.device.Id,
1765 "onu-id": onuID,
1766 "flow-id": flowID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001767 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1768 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1769 int32(onuID),
1770 int32(uniID),
1771 flowID, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301772 return olterrors.NewErrPersistence("update", "flow", flowID,
1773 log.Fields{
1774 "flow": downstreamflow,
1775 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001776 }
1777 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301778}
1779
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001780func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1781 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001782}
1783
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001784//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001785func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001786 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1787 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1788 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001789 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301790 log.Fields{
1791 "intf-id": intfID,
1792 "onu-id": onuID,
1793 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001794 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001795 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301796 return nil, olterrors.NewErrNotFound("onu-child-device",
1797 log.Fields{
1798 "onu-id": onuID,
1799 "intf-id": intfID,
1800 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001801 }
1802 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1803 //better to ad the device to cache here.
1804 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1805 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001806 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301807 log.Fields{
1808 "intf-id": intfID,
1809 "onu-id": onuID,
1810 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001811 }
1812
1813 return onuDev.(*OnuDevice), nil
1814}
1815
1816//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001817func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1818 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301819 log.Fields{
1820 "pon-port": intfID,
1821 "onu-id": onuID,
1822 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001823 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001824 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001825 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301826 return nil, olterrors.NewErrNotFound("onu",
1827 log.Fields{
1828 "interface-id": parentPortNo,
1829 "onu-id": onuID,
1830 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001831 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301832 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001833 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301834 log.Fields{
1835 "device-id": f.deviceHandler.device.Id,
1836 "child_device_id": onuDevice.Id,
1837 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301838 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301839}
1840
Neha Sharma96b7bf22020-06-15 10:37:32 +00001841func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1842 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301843 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001844 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301845 log.Fields{
1846 "intf-id": intfID,
1847 "onu-id": onuID,
1848 "uni-id": uniID,
1849 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001850 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301851 }
1852
1853 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001854 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301855 log.Fields{
1856 "msg": *delGemPortMsg,
1857 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001858 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301859 delGemPortMsg,
1860 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301861 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001862 onuDev.deviceType,
1863 onuDev.deviceID,
1864 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301865 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1866 log.Fields{
1867 "from-adapter": f.deviceHandler.device.Type,
1868 "to-adapter": onuDev.deviceType,
1869 "onu-id": onuDev.deviceID,
1870 "proxyDeviceID": onuDev.proxyDeviceID,
1871 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301872 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001873 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301874 log.Fields{
1875 "msg": delGemPortMsg,
1876 "from-adapter": f.deviceHandler.device.Type,
1877 "to-adapter": onuDev.deviceType,
1878 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301879 return nil
1880}
1881
Neha Sharma96b7bf22020-06-15 10:37:32 +00001882func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1883 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301884 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001885 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301886 log.Fields{
1887 "intf-id": intfID,
1888 "onu-id": onuID,
1889 "uni-id": uniID,
1890 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001891 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301892 }
1893
1894 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001895 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301896 log.Fields{
1897 "msg": *delTcontMsg,
1898 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001899 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301900 delTcontMsg,
1901 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301902 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001903 onuDev.deviceType,
1904 onuDev.deviceID,
1905 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301906 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1907 log.Fields{
1908 "from-adapter": f.deviceHandler.device.Type,
1909 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1910 "proxyDeviceID": onuDev.proxyDeviceID,
1911 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301912 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001913 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301914 log.Fields{
1915 "msg": delTcontMsg,
1916 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301917 return nil
1918}
1919
Neha Sharma96b7bf22020-06-15 10:37:32 +00001920func (f *OpenOltFlowMgr) deletePendingFlows(ctx context.Context, Intf uint32, onuID int32, uniID int32) {
Girish Gowdra3d633032019-12-10 16:37:05 +05301921 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1922 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1923 if val.(int) > 0 {
1924 pnFlDels := val.(int) - 1
1925 if pnFlDels > 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001926 logger.Debugw(ctx, "flow-delete-succeeded--more-pending",
Shrey Baid26912972020-04-16 21:02:31 +05301927 log.Fields{
1928 "intf": Intf,
1929 "onu-id": onuID,
1930 "uni-id": uniID,
1931 "currpendingflowcnt": pnFlDels,
1932 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301933 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1934 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001935 logger.Debugw(ctx, "all-pending-flow-deletes-handled--removing-entry-from-map",
Shrey Baid26912972020-04-16 21:02:31 +05301936 log.Fields{
1937 "intf": Intf,
1938 "onu-id": onuID,
1939 "uni-id": uniID,
1940 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301941 f.pendingFlowDelete.Delete(pnFlDelKey)
1942 }
1943 }
1944 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001945 logger.Debugw(ctx, "no-pending-delete-flows-found",
Shrey Baid26912972020-04-16 21:02:31 +05301946 log.Fields{
1947 "intf": Intf,
1948 "onu-id": onuID,
1949 "uni-id": uniID,
1950 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301951
1952 }
1953
1954}
1955
Girish Gowdrac3037402020-01-22 20:29:53 +05301956// Once the gemport is released for a given onu, it also has to be cleared from local cache
1957// which was used for deriving the gemport->logicalPortNo during packet-in.
1958// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1959// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001960func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001961
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001962 f.onuGemInfoLock.Lock()
1963 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001964
Neha Sharma96b7bf22020-06-15 10:37:32 +00001965 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301966 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001967 "gem-port-id": gemPortID,
1968 "intf-id": intfID,
1969 "onu-id": onuID,
1970 "device-id": f.deviceHandler.device.Id,
1971 "onu-gem": f.onuGemInfo[intfID]})
Girish Gowdrac3037402020-01-22 20:29:53 +05301972 onugem := f.onuGemInfo[intfID]
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001973deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001974 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301975 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001976 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301977 // If the gemport is found, delete it from local cache.
1978 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001979 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1980 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001981 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301982 log.Fields{
1983 "intf-id": intfID,
1984 "onu-id": onuID,
1985 "deletedgemport-id": gemPortID,
1986 "gemports": onu.GemPorts,
1987 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001988 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301989 }
1990 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001991 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301992 }
1993 }
1994}
1995
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301996//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001997// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301998func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301999 gemPortID int32, flowID uint32, flowDirection string,
2000 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002001
Neha Sharma96b7bf22020-06-15 10:37:32 +00002002 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002003 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302004 return olterrors.NewErrNotFound("tp-id",
2005 log.Fields{
2006 "flow": flow,
2007 "intf": Intf,
2008 "onu-id": onuID,
2009 "uni-id": uniID,
2010 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002011 }
Gamze Abakafee36392019-10-03 11:17:24 +00002012
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002013 if len(updatedFlows) >= 0 {
2014 // There are still flows referencing the same flow_id.
2015 // So the flow should not be freed yet.
2016 // For ex: Case of HSIA where same flow is shared
2017 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00002018 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002019 _ = olterrors.NewErrPersistence("update", "flow", flowID,
Shrey Baid26912972020-04-16 21:02:31 +05302020 log.Fields{
2021 "flow": updatedFlows,
2022 "device-id": f.deviceHandler.device.Id}, err).Log()
Girish Kumarf26e4882020-03-05 06:49:10 +00002023 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002024 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05302025 // Do this for subscriber flows only (not trap from NNI flows)
2026 if onuID != -1 && uniID != -1 {
2027 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
2028 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002029 logger.Debugw(ctx, "creating-entry-for-pending-flow-delete",
Shrey Baid26912972020-04-16 21:02:31 +05302030 log.Fields{
2031 "flow-id": flowID,
2032 "intf": Intf,
2033 "onu-id": onuID,
2034 "uni-id": uniID,
2035 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302036 f.pendingFlowDelete.Store(pnFlDelKey, 1)
2037 } else {
2038 pnFlDels := val.(int) + 1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002039 logger.Debugw(ctx, "updating-flow-delete-entry",
Shrey Baid26912972020-04-16 21:02:31 +05302040 log.Fields{
2041 "flow-id": flowID,
2042 "intf": Intf,
2043 "onu-id": onuID,
2044 "uni-id": uniID,
2045 "currPendingFlowCnt": pnFlDels,
2046 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302047 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
2048 }
2049
Neha Sharma96b7bf22020-06-15 10:37:32 +00002050 defer f.deletePendingFlows(ctx, Intf, onuID, uniID)
Girish Gowdra3d633032019-12-10 16:37:05 +05302051 }
2052
Neha Sharma96b7bf22020-06-15 10:37:32 +00002053 logger.Debugw(ctx, "releasing-flow-id-to-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302054 log.Fields{
2055 "Intf": Intf,
2056 "onu-id": onuID,
2057 "uni-id": uniID,
2058 "flow-id": flowID,
2059 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302060 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002061
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002062 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002063 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
2064 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
Shrey Baid26912972020-04-16 21:02:31 +05302065 log.Fields{
2066 "TP-PATH": tpPath,
2067 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302068 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00002069 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +05302070 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
2071 log.Fields{
2072 "tp-id": tpID,
2073 "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002074 }
2075
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302076 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002077 used, err := f.isGemPortUsedByAnotherFlow(ctx, gemPK)
2078 if err != nil {
2079 return err
2080 }
2081 if used {
2082 if f.perGemPortLock.TryLock(gemPK) {
2083 flowIDs := f.flowsUsedByGemPort[gemPK]
2084 for i, flowIDinMap := range flowIDs {
2085 if flowIDinMap == flowID {
2086 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
2087 // everytime flowsUsedByGemPort cache is updated the same should be updated
2088 // in kv store by calling UpdateFlowIDsForGem
2089 f.flowsUsedByGemPort[gemPK] = flowIDs
2090 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs); err != nil {
2091 return err
2092 }
2093 break
Kent Hagermane6ff1012020-07-14 15:07:53 -04002094 }
Gamze Abakafee36392019-10-03 11:17:24 +00002095 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002096 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
2097 log.Fields{
2098 "gemport-id": gemPortID,
2099 "usedByFlows": flowIDs,
2100 "device-id": f.deviceHandler.device.Id})
2101 f.perGemPortLock.Unlock(gemPK)
2102 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00002103 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002104
2105 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
Shrey Baid26912972020-04-16 21:02:31 +05302106 log.Fields{
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002107 "gemport-id": gemPortID,
2108 "device-id": f.deviceHandler.device.Id,
2109 "key": gemPK,
2110 })
2111 return olterrors.NewErrAdapter("failed-to-acquire-per-gem-port-lock", log.Fields{
2112 "gemport-id": gemPortID,
2113 "device-id": f.deviceHandler.device.Id,
2114 "key": gemPK,
2115 }, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00002116 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002117 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05302118 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002119 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
2120 // 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 +05302121 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002122 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002123 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302124 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
2125 // by calling DeleteFlowIDsForGem
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002126 if f.perGemPortLock.TryLock(gemPK) {
2127 delete(f.flowsUsedByGemPort, gemPK)
2128 f.perGemPortLock.Unlock(gemPK)
2129 } else {
2130 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
2131 log.Fields{
2132 "device-id": f.deviceHandler.device.Id,
2133 "key": gemPK,
2134 })
2135 }
npujarec5762e2020-01-01 14:08:48 +05302136 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
2137 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002138 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05302139 // Delete the gem port on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002140 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
2141 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302142 log.Fields{
2143 "err": err,
2144 "intf": Intf,
2145 "onu-id": onuID,
2146 "uni-id": uniID,
2147 "device-id": f.deviceHandler.device.Id,
2148 "gemport-id": gemPortID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302149 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002150 switch techprofileInst := techprofileInst.(type) {
2151 case *tp.TechProfile:
2152 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
2153 if !ok {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002154 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
2155 logger.Warn(ctx, err)
2156 }
2157 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2158 logger.Warn(ctx, err)
2159 }
2160 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 {
2161 logger.Warn(ctx, err)
2162 }
2163 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 {
2164 logger.Warn(ctx, err)
2165 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002166 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
2167 // Delete the TCONT on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002168 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
2169 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002170 log.Fields{
2171 "intf": Intf,
2172 "onu-id": onuID,
2173 "uni-id": uniID,
2174 "device-id": f.deviceHandler.device.Id,
2175 "alloc-id": techprofileInst.UsScheduler.AllocID})
2176 }
2177 }
2178 case *tp.EponProfile:
Kent Hagermane6ff1012020-07-14 15:07:53 -04002179 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
2180 logger.Warn(ctx, err)
2181 }
2182 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2183 logger.Warn(ctx, err)
2184 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002185 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302186 // Delete the TCONT on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002187 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.AllocID), tpPath); err != nil {
2188 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302189 log.Fields{
2190 "intf": Intf,
2191 "onu-id": onuID,
2192 "uni-id": uniID,
2193 "device-id": f.deviceHandler.device.Id,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002194 "alloc-id": techprofileInst.AllocID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302195 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002196 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002197 logger.Errorw(ctx, "error-unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002198 log.Fields{
2199 "techprofileInst": techprofileInst})
Gamze Abakafee36392019-10-03 11:17:24 +00002200 }
2201 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002202 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302203 return nil
2204}
2205
David K. Bainbridge794735f2020-02-11 21:01:37 -08002206// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302207func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302208
Neha Sharma96b7bf22020-06-15 10:37:32 +00002209 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302210 log.Fields{
2211 "flowDirection": flowDirection,
2212 "flow": *flow,
2213 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002214
2215 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05302216 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002217 return
2218 }
2219
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302220 classifierInfo := make(map[string]interface{})
2221
Neha Sharma96b7bf22020-06-15 10:37:32 +00002222 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302223 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002224 logger.Error(ctx, err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302225 return
2226 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302227
David K. Bainbridge794735f2020-02-11 21:01:37 -08002228 onuID := int32(onu)
2229 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302230
2231 for _, field := range flows.GetOfbFields(flow) {
2232 if field.Type == flows.IP_PROTO {
2233 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002234 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302235 }
2236 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002237 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302238 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002239 "flow-id": flow.Id,
2240 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302241 "onu-id": onuID,
2242 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302243
2244 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2245 onuID = -1
2246 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002247 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2248 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002249 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002250 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002251 log.Fields{
2252 "port-number": inPort,
2253 "error": err})
2254 return
2255 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302256 }
npujarec5762e2020-01-01 14:08:48 +05302257 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002258 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302259 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302260 if flowInfo == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002261 logger.Debugw(ctx, "no-flowinfo-found-in-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302262 log.Fields{
2263 "intf": Intf,
2264 "onu-id": onuID,
2265 "uni-id": uniID,
2266 "flow-id": flowID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302267 return
2268 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302269
Kent Hagermane6ff1012020-07-14 15:07:53 -04002270 updatedFlows := *flowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302271 for i, storedFlow := range updatedFlows {
2272 if flow.Id == storedFlow.LogicalFlowID {
2273 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002274 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002275 // DKB
Neha Sharma96b7bf22020-06-15 10:37:32 +00002276 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2277 logger.Errorw(ctx, "failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002278 return
2279 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002280 logger.Info(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002281 "flow-id": flow.Id,
2282 "stored-flow": storedFlow,
2283 "device-id": f.deviceHandler.device.Id,
2284 "stored-flow-id": flowID,
2285 "onu-id": onuID,
2286 "intf": Intf,
2287 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08002288 //Remove the Flow from FlowInfo
2289 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
2290 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
2291 flowID, flowDirection, portNum, updatedFlows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002292 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002293 "flow-id": flow.Id,
2294 "stored-flow": storedFlow,
2295 "device-id": f.deviceHandler.device.Id,
2296 "stored-flow-id": flowID,
2297 "onu-id": onuID,
2298 "intf": Intf,
2299 })
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302300 return
2301 }
2302 }
2303 }
2304 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002305}
2306
Esin Karamanccb714b2019-11-29 15:02:06 +00002307//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
2308// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05302309func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002310 classifierInfo := make(map[string]interface{})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002311 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00002312 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002313
2314 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002315 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 +00002316 return
2317 }
2318
Esin Karamanccb714b2019-11-29 15:02:06 +00002319 var onuID = int32(NoneOnuID)
2320 var uniID = int32(NoneUniID)
2321 var flowID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00002322
npujarec5762e2020-01-01 14:08:48 +05302323 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002324
2325 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302326 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002327 if flowInfo == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002328 logger.Debugw(ctx, "no-multicast-flowinfo-found-in-the-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302329 log.Fields{
2330 "intf": networkInterfaceID,
2331 "onu-id": onuID,
2332 "uni-id": uniID,
2333 "flow-id": flowID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002334 continue
2335 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002336 updatedFlows := *flowInfo
Esin Karamanccb714b2019-11-29 15:02:06 +00002337 for i, storedFlow := range updatedFlows {
2338 if flow.Id == storedFlow.LogicalFlowID {
2339 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002340 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302341 log.Fields{
2342 "flow": storedFlow,
2343 "flow-id": flow.Id,
2344 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002345 //remove from device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002346 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002347 // DKB
Neha Sharma96b7bf22020-06-15 10:37:32 +00002348 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002349 log.Fields{
2350 "flow-id": flow.Id,
2351 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002352 return
2353 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002354 logger.Infow(ctx, "multicast-flow-removed-from-device-successfully", log.Fields{"flow-id": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002355 //Remove the Flow from FlowInfo
2356 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05302357 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002358 logger.Errorw(ctx, "failed-to-delete-multicast-flow-from-the-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302359 log.Fields{"flow": storedFlow,
2360 "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002361 return
2362 }
2363 //release flow id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002364 logger.Debugw(ctx, "releasing-multicast-flow-id",
Shrey Baid26912972020-04-16 21:02:31 +05302365 log.Fields{"flow-id": flowID,
2366 "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05302367 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002368 }
2369 }
2370 }
2371}
2372
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002373//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002374func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002375 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302376 var direction string
2377 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002378
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302379 for _, action := range flows.GetActions(flow) {
2380 if action.Type == flows.OUTPUT {
2381 if out := action.GetOutput(); out != nil {
2382 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002383 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302384 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002385 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002386 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002387 }
2388 }
2389 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002390
2391 if flows.HasGroup(flow) {
2392 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07002393 f.clearFlowFromResourceManager(ctx, flow, direction)
2394 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002395 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302396 direction = Upstream
2397 } else {
2398 direction = Downstream
2399 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302400
Neha Sharma96b7bf22020-06-15 10:37:32 +00002401 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002402 if err != nil {
2403 return err
2404 }
2405
2406 userKey := tpLockKey{intfID, onuID, uniID}
2407
2408 // Serialize flow removes on a per subscriber basis
2409 if f.perUserFlowHandleLock.TryLock(userKey) {
2410 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
2411 f.perUserFlowHandleLock.Unlock(userKey)
2412 } else {
2413 // Ideally this should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00002414 logger.Errorw(ctx, "failed-to-acquire-lock-to-remove-flow--remove-aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07002415 return errors.New("failed-to-acquire-per-user-lock")
2416 }
2417
2418 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002419}
2420
Girish Gowdra3d633032019-12-10 16:37:05 +05302421func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
2422 uniID uint32, ch chan bool) {
2423 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2424 for {
2425 select {
2426 case <-time.After(20 * time.Millisecond):
2427 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002428 logger.Debug(ctx, "pending-flow-deletes-completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05302429 ch <- true
2430 return
2431 }
2432 case <-ctx.Done():
Neha Sharma96b7bf22020-06-15 10:37:32 +00002433 logger.Error(ctx, "flow-delete-wait-handler-routine-canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05302434 return
2435 }
2436 }
2437}
2438
Esin Karamanae41e2b2019-12-17 18:13:13 +00002439//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2440func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2441 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2442 if ethType, ok := classifierInfo[EthType]; ok {
2443 if ethType.(uint32) == IPv4EthType {
2444 if ipProto, ok := classifierInfo[IPProto]; ok {
2445 if ipProto.(uint32) == IgmpProto {
2446 return true
2447 }
2448 }
2449 }
2450 }
2451 }
2452 return false
2453}
2454
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002455// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302456// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002457func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002458 classifierInfo := make(map[string]interface{})
2459 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002460 var UsMeterID uint32
2461 var DsMeterID uint32
2462
Neha Sharma96b7bf22020-06-15 10:37:32 +00002463 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302464 log.Fields{
2465 "flow": flow,
2466 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002467 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002468
Neha Sharma96b7bf22020-06-15 10:37:32 +00002469 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002470 if err != nil {
2471 // Error logging is already done in the called function
2472 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002473 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302474 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002475
Esin Karamanccb714b2019-11-29 15:02:06 +00002476 if flows.HasGroup(flow) {
2477 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002478 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002479 }
2480
manikkaraj k17652a72019-05-06 09:06:36 -04002481 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002482 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002483 if err != nil {
2484 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002485 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002486 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002487
Neha Sharma96b7bf22020-06-15 10:37:32 +00002488 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302489 log.Fields{
2490 "classifierinfo_inport": classifierInfo[InPort],
2491 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002492 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002493
Humera Kouser94d7a842019-08-25 19:04:32 -04002494 if ethType, ok := classifierInfo[EthType]; ok {
2495 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002496 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002497 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002498 }
2499 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002500 if ipProto, ok := classifierInfo[IPProto]; ok {
2501 if ipProto.(uint32) == IPProtoDhcp {
2502 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302503 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002504 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002505 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002506 }
2507 }
2508 }
2509 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002510 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002511 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002512 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002513 }
A R Karthick1f85b802019-10-11 05:06:05 +00002514
npujarec5762e2020-01-01 14:08:48 +05302515 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002516
Neha Sharma96b7bf22020-06-15 10:37:32 +00002517 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002518 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302519 return olterrors.NewErrNotFound("tpid-for-flow",
2520 log.Fields{
2521 "flow": flow,
2522 "intf-id": IntfID,
2523 "onu-id": onuID,
2524 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002525 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002526 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302527 log.Fields{
2528 "tp-id": TpID,
2529 "intf-id": intfID,
2530 "onu-id": onuID,
2531 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002532 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002533 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002534 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002535 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002536 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002537 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002538
2539 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302540
2541 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2542 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002543 logger.Debugw(ctx, "no-pending-flows-found--going-ahead-with-flow-install",
Shrey Baid26912972020-04-16 21:02:31 +05302544 log.Fields{
2545 "intf-id": intfID,
2546 "onu-id": onuID,
2547 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302548 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302549 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05302550 pendingFlowDelComplete := make(chan bool)
2551 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
2552 select {
2553 case <-pendingFlowDelComplete:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002554 logger.Debugw(ctx, "all-pending-flow-deletes-completed",
Shrey Baid26912972020-04-16 21:02:31 +05302555 log.Fields{
2556 "intf-id": intfID,
2557 "onu-id": onuID,
2558 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302559 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302560
2561 case <-time.After(10 * time.Second):
Shrey Baid26912972020-04-16 21:02:31 +05302562 return olterrors.NewErrTimeout("pending-flow-deletes",
2563 log.Fields{
2564 "intf-id": intfID,
2565 "onu-id": onuID,
2566 "uni-id": uniID}, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +05302567 }
2568 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002569 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002570}
2571
Esin Karamanccb714b2019-11-29 15:02:06 +00002572// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002573func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002574 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002575 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302576 "classifier-info": classifierInfo,
2577 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002578
Esin Karaman65409d82020-03-18 10:58:18 +00002579 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002580 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002581 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002582 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002583 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
2584 //otherwise, classification is based on ipv4_dst by default.
2585 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
2586 mcastFlowClassificationByEthDst := false
2587
2588 if mcastFlowClassificationByEthDst {
2589 //replace ipDst with ethDst
2590 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
2591 flows.IsMulticastIp(ipv4Dst.(uint32)) {
2592 // replace ipv4_dst classifier with eth_dst
2593 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
2594 delete(classifierInfo, Ipv4Dst)
2595 classifierInfo[EthDst] = multicastMac
Neha Sharma96b7bf22020-06-15 10:37:32 +00002596 logger.Debugw(ctx, "multicast-ip-to-mac-conversion-success",
Shrey Baid26912972020-04-16 21:02:31 +05302597 log.Fields{
2598 "ip:": ipv4Dst.(uint32),
2599 "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002600 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002601 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002602 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002603
David K. Bainbridge794735f2020-02-11 21:01:37 -08002604 onuID := NoneOnuID
2605 uniID := NoneUniID
2606 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00002607
Neha Sharma96b7bf22020-06-15 10:37:32 +00002608 flowStoreCookie := getFlowStoreCookie(ctx, classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302609 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002610 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002611 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002612 }
npujarec5762e2020-01-01 14:08:48 +05302613 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00002614 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302615 return olterrors.NewErrNotFound("multicast-flow-id",
2616 log.Fields{
2617 "interface-id": networkInterfaceID,
2618 "onu-id": onuID,
2619 "uni-id": uniID,
2620 "gem-port-id": gemPortID,
2621 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002622 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002623 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002624 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2625 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002626 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002627 }
2628 groupID := actionInfo[GroupID].(uint32)
2629 multicastFlow := openoltpb2.Flow{
2630 FlowId: flowID,
2631 FlowType: Multicast,
2632 NetworkIntfId: int32(networkInterfaceID),
2633 GroupId: groupID,
2634 Classifier: classifierProto,
2635 Priority: int32(flow.Priority),
2636 Cookie: flow.Cookie}
2637
Kent Hagermane6ff1012020-07-14 15:07:53 -04002638 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002639 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002640 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002641 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002642 //get cached group
Kent Hagermane6ff1012020-07-14 15:07:53 -04002643 if group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002644 //calling groupAdd to set group members after multicast flow creation
Kent Hagermane6ff1012020-07-14 15:07:53 -04002645 if err := f.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002646 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002647 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002648 //cached group can be removed now
2649 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2650 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2651 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002652 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002653
2654 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2655 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2656 int32(onuID),
2657 int32(uniID),
2658 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002659 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002660 }
2661 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002662}
2663
Esin Karaman65409d82020-03-18 10:58:18 +00002664//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2665func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2666 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002667 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002668 if err != nil {
2669 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2670 }
2671 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002672 }
Esin Karaman65409d82020-03-18 10:58:18 +00002673 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302674 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002675 if e == nil && len(nniPorts) > 0 {
2676 return nniPorts[0], nil
2677 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302678 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002679}
2680
2681// AddGroup add or update the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002682func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002683 logger.Infow(ctx, "add-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002684 if group == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002685 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002686 }
2687
2688 groupToOlt := openoltpb2.Group{
2689 GroupId: group.Desc.GroupId,
2690 Command: openoltpb2.Group_SET_MEMBERS,
2691 Action: f.buildGroupAction(),
2692 }
2693
Neha Sharma96b7bf22020-06-15 10:37:32 +00002694 logger.Debugw(ctx, "sending-group-to-device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05302695 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002696 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002697 return olterrors.NewErrAdapter("add-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002698 }
2699 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05302700 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002701 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002702 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002703 logger.Infow(ctx, "add-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002704 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002705}
2706
Esin Karamand519bbf2020-07-01 11:16:03 +00002707// DeleteGroup deletes a group from the device
2708func (f *OpenOltFlowMgr) DeleteGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
2709 logger.Debugw(ctx, "delete-group", log.Fields{"group": group})
2710 if group == nil {
2711 logger.Error(ctx, "unable-to-delete-group--invalid-argument--group-is-nil")
2712 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
2713 }
2714
2715 groupToOlt := openoltpb2.Group{
2716 GroupId: group.Desc.GroupId,
2717 }
2718
2719 logger.Debugw(ctx, "deleting-group-from-device", log.Fields{"groupToOlt": groupToOlt})
2720 _, err := f.deviceHandler.Client.DeleteGroup(ctx, &groupToOlt)
2721 if err != nil {
2722 logger.Errorw(ctx, "delete-group-failed-on-dev", log.Fields{"groupToOlt": groupToOlt, "err": err})
2723 return olterrors.NewErrAdapter("delete-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
2724 }
2725 //remove group from the store
2726 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, group.Desc.GroupId, false); err != nil {
2727 return olterrors.NewErrPersistence("delete", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
2728 }
2729 logger.Debugw(ctx, "delete-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
2730 return nil
2731}
2732
Esin Karamanccb714b2019-11-29 15:02:06 +00002733//buildGroupAction creates and returns a group action
2734func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2735 var actionCmd openoltpb2.ActionCmd
2736 var action openoltpb2.Action
2737 action.Cmd = &actionCmd
2738 //pop outer vlan
2739 action.Cmd.RemoveOuterTag = true
2740 return &action
2741}
2742
2743// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002744func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002745 logger.Infow(ctx, "modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002746 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002747 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002748 }
2749
Neha Sharma96b7bf22020-06-15 10:37:32 +00002750 newGroup := f.buildGroup(ctx, group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002751 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302752 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002753
2754 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002755 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002756 }
2757
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002758 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002759 if groupExists {
2760 // group already exists
Neha Sharma96b7bf22020-06-15 10:37:32 +00002761 current = f.buildGroup(ctx, group.Desc.GroupId, val.Desc.GetBuckets())
2762 logger.Debugw(ctx, "modify-group--group exists",
Shrey Baid26912972020-04-16 21:02:31 +05302763 log.Fields{
2764 "group on the device": val,
2765 "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002766 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002767 current = f.buildGroup(ctx, group.Desc.GroupId, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002768 }
2769
Neha Sharma96b7bf22020-06-15 10:37:32 +00002770 logger.Debugw(ctx, "modify-group--comparing-current-and-new",
Shrey Baid26912972020-04-16 21:02:31 +05302771 log.Fields{
2772 "group on the device": current,
2773 "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002774 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002775 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002776 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002777 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002778
Neha Sharma96b7bf22020-06-15 10:37:32 +00002779 logger.Infow(ctx, "modify-group--differences found", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302780 "membersToBeAdded": membersToBeAdded,
2781 "membersToBeRemoved": membersToBeRemoved,
2782 "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002783
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002784 groupToOlt := openoltpb2.Group{
2785 GroupId: group.Desc.GroupId,
2786 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002787 var errAdd, errRemoved error
Kent Hagermane6ff1012020-07-14 15:07:53 -04002788 if len(membersToBeAdded) > 0 {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002789 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2790 groupToOlt.Members = membersToBeAdded
2791 //execute addMembers
Neha Sharma96b7bf22020-06-15 10:37:32 +00002792 errAdd = f.callGroupAddRemove(ctx, &groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002793 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002794 if len(membersToBeRemoved) > 0 {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002795 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2796 groupToOlt.Members = membersToBeRemoved
2797 //execute removeMembers
Neha Sharma96b7bf22020-06-15 10:37:32 +00002798 errRemoved = f.callGroupAddRemove(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002799 }
2800
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002801 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002802 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302803 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002804 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002805 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002806 logger.Infow(ctx, "modify-group-was-success--storing-group",
Shrey Baid26912972020-04-16 21:02:31 +05302807 log.Fields{
2808 "group": group,
2809 "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002810 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002811 logger.Warnw(ctx, "one-of-the-group-add/remove-operations-failed--cannot-save-group-modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002812 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002813 if errAdd != nil {
2814 return errAdd
2815 }
2816 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002817 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002818 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002819}
2820
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002821//callGroupAddRemove performs add/remove buckets operation for the indicated group
Neha Sharma96b7bf22020-06-15 10:37:32 +00002822func (f *OpenOltFlowMgr) callGroupAddRemove(ctx context.Context, group *openoltpb2.Group) error {
2823 if err := f.performGroupOperation(ctx, group); err != nil {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002824 st, _ := status.FromError(err)
2825 //ignore already exists error code
2826 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002827 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002828 }
2829 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002830 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002831}
2832
2833//findDiff compares group members and finds members which only exists in groups2
2834func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2835 var members []*openoltpb2.GroupMember
2836 for _, bucket := range group2.Members {
2837 if !f.contains(group1.Members, bucket) {
2838 // bucket does not exist and must be added
2839 members = append(members, bucket)
2840 }
2841 }
2842 return members
2843}
2844
2845//contains returns true if the members list contains the given member; false otherwise
2846func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2847 for _, groupMember := range members {
2848 if groupMember.InterfaceId == member.InterfaceId {
2849 return true
2850 }
2851 }
2852 return false
2853}
2854
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002855//performGroupOperation call performGroupOperation operation of openolt proto
Neha Sharma96b7bf22020-06-15 10:37:32 +00002856func (f *OpenOltFlowMgr) performGroupOperation(ctx context.Context, group *openoltpb2.Group) error {
2857 logger.Debugw(ctx, "sending-group-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05302858 log.Fields{
2859 "groupToOlt": group,
2860 "command": group.Command})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002861 _, err := f.deviceHandler.Client.PerformGroupOperation(log.WithSpanFromContext(context.Background(), ctx), group)
Esin Karamanccb714b2019-11-29 15:02:06 +00002862 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002863 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002864 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002865 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002866}
2867
2868//buildGroup build openoltpb2.Group from given group id and bucket list
Neha Sharma96b7bf22020-06-15 10:37:32 +00002869func (f *OpenOltFlowMgr) buildGroup(ctx context.Context, groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
Esin Karamanccb714b2019-11-29 15:02:06 +00002870 group := openoltpb2.Group{
2871 GroupId: groupID}
2872 // create members of the group
Kent Hagermane6ff1012020-07-14 15:07:53 -04002873 for _, ofBucket := range buckets {
2874 member := f.buildMember(ctx, ofBucket)
2875 if member != nil && !f.contains(group.Members, member) {
2876 group.Members = append(group.Members, member)
Esin Karamanccb714b2019-11-29 15:02:06 +00002877 }
2878 }
2879 return &group
2880}
2881
2882//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
Neha Sharma96b7bf22020-06-15 10:37:32 +00002883func (f *OpenOltFlowMgr) buildMember(ctx context.Context, ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
Esin Karamanccb714b2019-11-29 15:02:06 +00002884 var outPort uint32
2885 outPortFound := false
2886 for _, ofAction := range ofBucket.Actions {
2887 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2888 outPort = ofAction.GetOutput().Port
2889 outPortFound = true
2890 }
2891 }
2892
2893 if !outPortFound {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002894 logger.Debugw(ctx, "bucket-skipped-since-no-out-port-found-in-it", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002895 return nil
2896 }
2897 interfaceID := IntfIDFromUniPortNum(outPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002898 logger.Debugw(ctx, "got-associated-interface-id-of-the-port",
Shrey Baid26912972020-04-16 21:02:31 +05302899 log.Fields{
2900 "portNumber:": outPort,
2901 "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002902 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2903 member := openoltpb2.GroupMember{
2904 InterfaceId: interfaceID,
2905 InterfaceType: openoltpb2.GroupMember_PON,
2906 GemPortId: groupInfo.gemPortID,
2907 Priority: groupInfo.servicePriority,
2908 }
2909 //add member to the group
2910 return &member
2911 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002912 logger.Warnf(ctx, "bucket-skipped-since-interface-2-gem-mapping-cannot-be-found", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002913 return nil
2914}
2915
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002916//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002917func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002918
Neha Sharma96b7bf22020-06-15 10:37:32 +00002919 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302920 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002921 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302922 log.Fields{
2923 "intf-id": intfID,
2924 "onu-id": onuID,
2925 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002926 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302927 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002928 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002929
Neha Sharma96b7bf22020-06-15 10:37:32 +00002930 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002931 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002932 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002933 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002934 tpDownloadMsg,
2935 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302936 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002937 onuDev.deviceType,
2938 onuDev.deviceID,
2939 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002940 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302941 return olterrors.NewErrCommunication("send-techprofile-download-request",
2942 log.Fields{
2943 "from-adapter": f.deviceHandler.device.Type,
2944 "to-adapter": onuDev.deviceType,
2945 "onu-id": onuDev.deviceID,
2946 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002947 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002948 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302949 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302950}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002951
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302952//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002953func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302954
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002955 f.onuGemInfoLock.Lock()
2956 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002957
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302958 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2959 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002960 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002961 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302962 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002963 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302964 log.Fields{
2965 "intf-id": intfID,
2966 "onu-id": onuID,
2967 "serial-num": serialNum,
2968 "onu": onu,
2969 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002970 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002971}
2972
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302973//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302974func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002975
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002976 f.onuGemInfoLock.Lock()
2977 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002978
Neha Sharma96b7bf22020-06-15 10:37:32 +00002979 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302980 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002981 "gem-port-id": gemPort,
2982 "intf-id": intfID,
2983 "onu-id": onuID,
2984 "device-id": f.deviceHandler.device.Id,
2985 "onu-gem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302986 onugem := f.onuGemInfo[intfID]
2987 // update the gem to the local cache as well as to kv strore
2988 for idx, onu := range onugem {
2989 if onu.OnuID == onuID {
2990 // check if gem already exists , else update the cache and kvstore
2991 for _, gem := range onu.GemPorts {
2992 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002993 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302994 log.Fields{
2995 "gem": gemPort,
2996 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302997 return
2998 }
2999 }
3000 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
3001 f.onuGemInfo[intfID] = onugem
3002 }
3003 }
npujarec5762e2020-01-01 14:08:48 +05303004 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303005 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003006 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05303007 log.Fields{
3008 "intf-id": intfID,
3009 "onu-id": onuID,
3010 "gemPort": gemPort,
3011 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003012 return
3013 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003014 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05303015 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003016 "gem-port-id": gemPort,
3017 "intf-id": intfID,
3018 "onu-id": onuID,
3019 "device-id": f.deviceHandler.device.Id,
3020 "onu-gem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003021}
3022
3023// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003024
3025//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 +00003026func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303027
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003028 f.onuGemInfoLock.RLock()
3029 defer f.onuGemInfoLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303030
Neha Sharma96b7bf22020-06-15 10:37:32 +00003031 logger.Infow(ctx, "getting-onu-id-from-gem-port-and-pon-port",
Shrey Baid26912972020-04-16 21:02:31 +05303032 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003033 "device-id": f.deviceHandler.device.Id,
3034 "onu-geminfo": f.onuGemInfo[intfID],
3035 "intf-id": intfID,
3036 "gemport-id": gemPortID})
Matteo Scandolod625b4c2020-04-02 16:16:01 -07003037
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303038 // get onuid from the onugem info cache
3039 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07003040
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303041 for _, onu := range onugem {
3042 for _, gem := range onu.GemPorts {
3043 if gem == gemPortID {
3044 return onu.OnuID, nil
3045 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003046 }
3047 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003048 logger.Errorw(ctx, "onu-id-from-gem-port-not-found", log.Fields{
3049 "gem-port-id": gemPortID,
3050 "interface-id": intfID,
Kent Hagermane6ff1012020-07-14 15:07:53 -04003051 "all-gems-on-port": onugem,
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003052 })
Thomas Lee S94109f12020-03-03 16:39:29 +05303053 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003054 "interface-id": intfID,
3055 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00003056 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003057}
3058
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003059//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05303060func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003061 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003062 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003063 var err error
3064
3065 if packetIn.IntfType == "pon" {
3066 // packet indication does not have serial number , so sending as nil
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067 if onuID, err = f.getOnuIDfromGemPortMap(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003068 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003069 return logicalPortNum, err
3070 }
3071 if packetIn.PortNo != 0 {
3072 logicalPortNum = packetIn.PortNo
3073 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003074 uniID := uint32(0) // FIXME - multi-uni support
Neha Sharma96b7bf22020-06-15 10:37:32 +00003075 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003076 }
3077 // 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 +00003078 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003079 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003080 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003081 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003082 logger.Infow(ctx, "retrieved-logicalport-from-packet-in",
Shrey Baid26912972020-04-16 21:02:31 +05303083 log.Fields{
3084 "logical-port-num": logicalPortNum,
3085 "intf-type": packetIn.IntfType,
3086 "packet": hex.EncodeToString(packetIn.Pkt),
3087 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003088 return logicalPortNum, nil
3089}
3090
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003091//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00003092func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003093 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00003094
3095 ctag, priority, err := getCTagFromPacket(ctx, packet)
3096 if err != nil {
3097 return 0, err
3098 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303099
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003100 f.onuGemInfoLock.RLock()
3101 defer f.onuGemInfoLock.RUnlock()
Esin Karaman7fb80c22020-07-16 14:23:33 +00003102 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003103 var ok bool
3104 gemPortID, ok = f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303105 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003106 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05303107 log.Fields{
3108 "pktinkey": pktInkey,
3109 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003110
3111 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003112 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303113 //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 +00003114 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303115 if err == nil {
3116 if gemPortID != 0 {
3117 f.packetInGemPort[pktInkey] = gemPortID
Neha Sharma96b7bf22020-06-15 10:37:32 +00003118 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05303119 log.Fields{
3120 "pktinkey": pktInkey,
3121 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303122 return gemPortID, nil
3123 }
3124 }
Shrey Baid26912972020-04-16 21:02:31 +05303125 return uint32(0), olterrors.NewErrNotFound("gem-port",
3126 log.Fields{
3127 "pktinkey": pktInkey,
3128 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003129
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003130}
3131
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003132// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303133func installFlowOnAllGemports(ctx context.Context,
3134 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003135 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003136 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05303137 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303138 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303139 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003140 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003141 args map[string]uint32,
3142 classifier map[string]interface{}, action map[string]interface{},
3143 logicalFlow *ofp.OfpFlowStats,
3144 gemPorts []uint32,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003145 TpInst interface{},
Manikkaraj kb1d51442019-07-23 10:41:02 -04003146 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00003147 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003148 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003149 vlanID ...uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003150 logger.Debugw(ctx, "installing-flow-on-all-gem-ports",
Shrey Baid26912972020-04-16 21:02:31 +05303151 log.Fields{
3152 "FlowType": FlowType,
3153 "gemPorts": gemPorts,
3154 "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05303155
Gamze Abaka724d0852020-03-18 12:10:24 +00003156 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
3157 // We need to trim prefix "0b", before further processing
3158 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
3159 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
3160
3161 // If a particular character in the string is set to '1', identify the index of this character from
3162 // the LSB position which marks the PCP bit consumed by the given gem port.
3163 // This PCP bit now becomes a classifier in the flow.
3164
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003165 switch TpInst := TpInst.(type) {
3166 case *tp.TechProfile:
3167 attributes := TpInst.DownstreamGemPortAttributeList
3168 if direction == Upstream {
3169 attributes = TpInst.UpstreamGemPortAttributeList
Gamze Abaka724d0852020-03-18 12:10:24 +00003170 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003171
3172 for _, gemPortAttribute := range attributes {
3173 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
3174 continue
Gamze Abaka724d0852020-03-18 12:10:24 +00003175 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003176 gemPortID := gemPortAttribute.GemportID
3177 if allPbitsMarked(gemPortAttribute.PbitMap) {
3178 classifier[VlanPcp] = uint32(VlanPCPMask)
3179 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003180 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3181 logger.Warn(ctx, err)
3182 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003183 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003184 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3185 logger.Warn(ctx, err)
3186 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003187 }
3188 } else {
3189 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
3190 if pbitSet == BinaryBit1 {
3191 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3192 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003193 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3194 logger.Warn(ctx, err)
3195 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003196 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003197 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3198 logger.Warn(ctx, err)
3199 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003200 }
3201 }
3202 }
3203 }
3204 }
3205 case *tp.EponProfile:
3206 if direction == Upstream {
3207 attributes := TpInst.UpstreamQueueAttributeList
3208 for _, queueAttribute := range attributes {
3209 gemPortID := queueAttribute.GemportID
3210 if allPbitsMarked(queueAttribute.PbitMap) {
3211 classifier[VlanPcp] = uint32(VlanPCPMask)
Gamze Abaka724d0852020-03-18 12:10:24 +00003212 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003213 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3214 logger.Warn(ctx, err)
3215 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003216 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003217 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3218 logger.Warn(ctx, err)
3219 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003220 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003221 } else {
3222 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3223 if pbitSet == BinaryBit1 {
3224 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3225 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003226 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3227 logger.Warn(ctx, err)
3228 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003229 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003230 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3231 logger.Warn(ctx, err)
3232 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003233 }
3234 }
3235 }
3236 }
3237 }
3238 } else {
3239 attributes := TpInst.DownstreamQueueAttributeList
3240 for _, queueAttribute := range attributes {
3241 gemPortID := queueAttribute.GemportID
3242 if allPbitsMarked(queueAttribute.PbitMap) {
3243 classifier[VlanPcp] = uint32(VlanPCPMask)
3244 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003245 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3246 logger.Warn(ctx, err)
3247 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003248 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003249 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3250 logger.Warn(ctx, err)
3251 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003252 }
3253 } else {
3254 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3255 if pbitSet == BinaryBit1 {
3256 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3257 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003258 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3259 logger.Warn(ctx, err)
3260 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003261 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003262 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3263 logger.Warn(ctx, err)
3264 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003265 }
3266 }
3267 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05303268 }
3269 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04003270 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003271 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003272 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpInst": TpInst})
Manikkaraj kb1d51442019-07-23 10:41:02 -04003273 }
3274}
3275
Gamze Abaka724d0852020-03-18 12:10:24 +00003276func allPbitsMarked(pbitMap string) bool {
3277 for pos, pBit := range pbitMap {
3278 if pos >= 2 && pBit != BinaryBit1 {
3279 return false
3280 }
3281 }
3282 return true
3283}
3284
David K. Bainbridge794735f2020-02-11 21:01:37 -08003285func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003286 logger.Debug(ctx, "adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003287 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003288 classifier[PacketTagType] = DoubleTag
3289 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003290 /* We manage flowId resource pool on per PON port basis.
3291 Since this situation is tricky, as a hack, we pass the NNI port
3292 index (network_intf_id) as PON port Index for the flowId resource
3293 pool. Also, there is no ONU Id available for trapping DHCP packets
3294 on NNI port, use onu_id as -1 (invalid)
3295 ****************** CAVEAT *******************
3296 This logic works if the NNI Port Id falls within the same valid
3297 range of PON Port Ids. If this doesn't work for some OLT Vendor
3298 we need to have a re-look at this.
3299 *********************************************
3300 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003301 onuID := -1
3302 uniID := -1
3303 gemPortID := -1
3304 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00003305 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303306 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303307 return olterrors.NewErrNotFound("nni-intreface-id",
3308 log.Fields{
3309 "classifier": classifier,
3310 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003311 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303312 }
3313
Neha Sharma96b7bf22020-06-15 10:37:32 +00003314 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303315 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003316 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003317 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003318 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003319 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003320 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303321 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id",
3322 log.Fields{
3323 "interface-id": networkInterfaceID,
3324 "onu-id": onuID,
3325 "uni-id": uniID,
3326 "gem-port-id": gemPortID,
3327 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003328 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003329 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003330 classifierProto, err := makeOpenOltClassifierField(classifier)
3331 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003332 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003333 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003334 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003335 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003336 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003337 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003338 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003339 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003340 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3341 OnuId: int32(onuID), // OnuId not required
3342 UniId: int32(uniID), // UniId not used
3343 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07003344 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003345 AllocId: int32(allocID), // AllocId not used
3346 NetworkIntfId: int32(networkInterfaceID),
3347 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003348 Classifier: classifierProto,
3349 Action: actionProto,
3350 Priority: int32(logicalFlow.Priority),
3351 Cookie: logicalFlow.Cookie,
3352 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003353 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003354 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003355 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003356 logger.Info(ctx, "dhcp-trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003357 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3358 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3359 int32(onuID),
3360 int32(uniID),
3361 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003362 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003363 }
3364 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003365}
salmansiddiqui7ac62132019-08-22 03:58:50 +00003366
Esin Karamanae41e2b2019-12-17 18:13:13 +00003367//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
3368func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
3369 var packetType string
3370 ovid, ivid := false, false
3371 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
3372 vid := vlanID & VlanvIDMask
3373 if vid != ReservedVlan {
3374 ovid = true
3375 }
3376 }
3377 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
3378 vid := uint32(metadata)
3379 if vid != ReservedVlan {
3380 ivid = true
3381 }
3382 }
3383 if ovid && ivid {
3384 packetType = DoubleTag
3385 } else if !ovid && !ivid {
3386 packetType = Untagged
3387 } else {
3388 packetType = SingleTag
3389 }
3390 return packetType
3391}
3392
3393//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08003394func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003395 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003396 action := make(map[string]interface{})
3397 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
3398 action[TrapToHost] = true
3399 /* We manage flowId resource pool on per PON port basis.
3400 Since this situation is tricky, as a hack, we pass the NNI port
3401 index (network_intf_id) as PON port Index for the flowId resource
3402 pool. Also, there is no ONU Id available for trapping packets
3403 on NNI port, use onu_id as -1 (invalid)
3404 ****************** CAVEAT *******************
3405 This logic works if the NNI Port Id falls within the same valid
3406 range of PON Port Ids. If this doesn't work for some OLT Vendor
3407 we need to have a re-look at this.
3408 *********************************************
3409 */
3410 onuID := -1
3411 uniID := -1
3412 gemPortID := -1
3413 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00003414 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003415 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303416 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003417 "classifier": classifier,
3418 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003419 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003420 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003421 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303422 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003423 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003424 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003425 }
npujarec5762e2020-01-01 14:08:48 +05303426 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003427 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303428 return olterrors.NewErrNotFound("igmp-flow-id",
3429 log.Fields{
3430 "interface-id": networkInterfaceID,
3431 "onu-id": onuID,
3432 "uni-id": uniID,
3433 "gem-port-id": gemPortID,
3434 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003435 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003436 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003437 classifierProto, err := makeOpenOltClassifierField(classifier)
3438 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003439 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003440 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003441 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003442 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003443 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003444 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003445 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003446 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003447 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3448 OnuId: int32(onuID), // OnuId not required
3449 UniId: int32(uniID), // UniId not used
3450 FlowId: flowID,
3451 FlowType: Downstream,
3452 AllocId: int32(allocID), // AllocId not used
3453 NetworkIntfId: int32(networkInterfaceID),
3454 GemportId: int32(gemPortID), // GemportId not used
3455 Classifier: classifierProto,
3456 Action: actionProto,
3457 Priority: int32(logicalFlow.Priority),
3458 Cookie: logicalFlow.Cookie,
3459 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003460 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003461 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003462 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003463 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003464 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3465 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3466 int32(onuID),
3467 int32(uniID),
3468 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003469 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003470 }
3471 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003472}
3473
salmansiddiqui7ac62132019-08-22 03:58:50 +00003474func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
3475 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05303476 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003477 }
3478 if Dir == tp_pb.Direction_UPSTREAM {
3479 return "upstream", nil
3480 } else if Dir == tp_pb.Direction_DOWNSTREAM {
3481 return "downstream", nil
3482 }
3483 return "", nil
3484}
3485
Kent Hagermane6ff1012020-07-14 15:07:53 -04003486// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303487func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003488 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003489 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00003490 var gemPort uint32
3491 intfID := args[IntfID]
3492 onuID := args[OnuID]
3493 uniID := args[UniID]
3494 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003495 allocID := args[AllocID]
salmansiddiqui7ac62132019-08-22 03:58:50 +00003496 if ipProto, ok := classifierInfo[IPProto]; ok {
3497 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003498 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003499 "tp-id": tpID,
3500 "alloc-id": allocID,
3501 "intf-id": intfID,
3502 "onu-id": onuID,
3503 "uni-id": uniID,
3504 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003505 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003506 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003507 tp_pb.Direction_UPSTREAM,
3508 pcp.(uint32))
3509 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00003510
Kent Hagermane6ff1012020-07-14 15:07:53 -04003511 if err := f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3512 logger.Warn(ctx, err)
3513 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003514 } else {
3515 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003516 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003517 }
3518
Girish Gowdra32625212020-04-29 11:26:35 -07003519 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003520 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05303521 log.Fields{
3522 "intf-id": intfID,
3523 "onu-id": onuID,
3524 "uni-id": uniID,
3525 "classifier-info:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003526 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003527 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
Esin Karamanae41e2b2019-12-17 18:13:13 +00003528 tp_pb.Direction_UPSTREAM,
3529 pcp.(uint32))
Kent Hagermane6ff1012020-07-14 15:07:53 -04003530 if err := f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3531 logger.Warn(ctx, err)
3532 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00003533 } else {
3534 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003535 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003536 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003537 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003538 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003539 return
3540 }
3541 } else if ethType, ok := classifierInfo[EthType]; ok {
3542 if ethType.(uint32) == EapEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003543 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003544 "intf-id": intfID,
3545 "onu-id": onuID,
3546 "uni-id": uniID,
3547 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003548 var vlanID uint32
3549 if val, ok := classifierInfo[VlanVid]; ok {
3550 vlanID = (val.(uint32)) & VlanvIDMask
3551 } else {
3552 vlanID = DefaultMgmtVlan
3553 }
3554 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003555 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003556 tp_pb.Direction_UPSTREAM,
3557 pcp.(uint32))
3558
Kent Hagermane6ff1012020-07-14 15:07:53 -04003559 if err := f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID); err != nil {
3560 logger.Warn(ctx, err)
3561 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003562 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003563 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003564 }
3565 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003566 } else if _, ok := actionInfo[PushVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003567 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003568 "intf-id": intfID,
3569 "onu-id": onuID,
3570 "uni-id": uniID,
3571 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003572 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003573 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003574 tp_pb.Direction_UPSTREAM,
3575 pcp.(uint32))
3576 //Adding HSIA upstream flow
Kent Hagermane6ff1012020-07-14 15:07:53 -04003577 if err := f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3578 logger.Warn(ctx, err)
3579 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003580 } else {
3581 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003582 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003583 }
3584 } else if _, ok := actionInfo[PopVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003585 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003586 "intf-id": intfID,
3587 "onu-id": onuID,
3588 "uni-id": uniID,
3589 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003590 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003591 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05003592 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003593 pcp.(uint32))
3594 //Adding HSIA downstream flow
Kent Hagermane6ff1012020-07-14 15:07:53 -04003595 if err := f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3596 logger.Warn(ctx, err)
3597 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003598 } else {
3599 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003600 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003601 }
3602 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003603 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05303604 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003605 "intf-id": intfID,
3606 "onu-id": onuID,
3607 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05303608 "classifier": classifierInfo,
3609 "action": actionInfo,
3610 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003611 return
3612 }
3613 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04003614 go func() {
3615 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
3616 logger.Warn(ctx, err)
3617 }
3618 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003619}
3620
Matteo Scandolo738c52a2020-08-03 11:14:22 -07003621func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(ctx context.Context, gemPK gemPortKey) (bool, error) {
3622 if f.perGemPortLock.TryLock(gemPK) {
3623 flowIDList := f.flowsUsedByGemPort[gemPK]
3624 f.perGemPortLock.Unlock(gemPK)
3625 return len(flowIDList) > 1, nil
3626 }
3627 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
3628 log.Fields{
3629 "device-id": f.deviceHandler.device.Id,
3630 "key": gemPK,
3631 })
3632 return false, olterrors.NewErrAdapter("failed-to-acquire-per-gem-port-lock", log.Fields{
3633 "device-id": f.deviceHandler.device.Id,
3634 "key": gemPK,
3635 }, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003636}
3637
npujarec5762e2020-01-01 14:08:48 +05303638func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3639 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003640 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3641 for _, currentGemPort := range currentGemPorts {
3642 for _, tpGemPort := range tpGemPorts {
3643 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3644 return true, currentGemPort
3645 }
3646 }
3647 }
Girish Gowdra54934262019-11-13 14:19:55 +05303648 if tpInst.InstanceCtrl.Onu == "single-instance" {
3649 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Kent Hagermane6ff1012020-07-14 15:07:53 -04003650 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID); err != nil {
3651 logger.Warn(ctx, err)
3652 }
3653 if err := f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
3654 logger.Warn(ctx, err)
3655 }
Girish Gowdra54934262019-11-13 14:19:55 +05303656
3657 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3658 // still be used on other uni ports.
3659 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3660 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003661 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003662 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303663 for i := 0; i < len(tpInstances); i++ {
3664 tpI := tpInstances[i]
3665 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303666 for _, tpGemPort := range tpGemPorts {
3667 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003668 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303669 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303670 }
3671 }
3672 }
3673 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003674 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003675 return false, 0
3676}
3677
Neha Sharma96b7bf22020-06-15 10:37:32 +00003678func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003679 for _, field := range flows.GetOfbFields(flow) {
3680 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003681 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003682 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003683 } else if field.Type == flows.ETH_DST {
3684 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003685 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003686 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003687 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003688 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003689 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003690 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003691 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003692 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303693 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003694 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003695 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003696 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003697 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003698 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003699 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003700 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003701 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003702 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003703 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003704 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003705 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003706 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003707 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003708 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003709 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003710 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003711 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003712 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003713 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003714 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003715 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003716 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003717 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003718 return
3719 }
3720 }
3721}
3722
Neha Sharma96b7bf22020-06-15 10:37:32 +00003723func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003724 for _, action := range flows.GetActions(flow) {
3725 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003726 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003727 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003728 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003729 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003730 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003731 }
Scott Baker355d1742019-10-24 10:57:52 -07003732 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003733 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003734 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003735 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003736 if out := action.GetPush(); out != nil {
3737 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003738 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003739 } else {
3740 actionInfo[PushVlan] = true
3741 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003742 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303743 log.Fields{
3744 "push-tpid": actionInfo[TPID].(uint32),
3745 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003746 }
3747 }
Scott Baker355d1742019-10-24 10:57:52 -07003748 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003749 if out := action.GetSetField(); out != nil {
3750 if field := out.GetField(); field != nil {
3751 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003752 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003753 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003754 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3755 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003756 }
3757 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003758 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003759 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003760 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003761 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003762 }
3763 }
3764 return nil
3765}
3766
Neha Sharma96b7bf22020-06-15 10:37:32 +00003767func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003768 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003769 fieldtype := ofbField.GetType()
3770 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003771 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3772 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003773 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003774 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003775 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003776 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003777 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3778 pcp := ofbField.GetVlanPcp()
3779 actionInfo[VlanPcp] = pcp
3780 log.Debugw("action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003781 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003782 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003783 }
3784 }
3785}
3786
Neha Sharma96b7bf22020-06-15 10:37:32 +00003787func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003788 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003789 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003790 } else {
3791 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003792 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003793 }
3794}
3795
Neha Sharma96b7bf22020-06-15 10:37:32 +00003796func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003797 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003798 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003799 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3800 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003801 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003802 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003803 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303804 log.Fields{
3805 "newinport": classifierInfo[InPort].(uint32),
3806 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003807 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303808 return olterrors.NewErrNotFound("child-in-port",
3809 log.Fields{
3810 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3811 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003812 }
3813 }
3814 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003815 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003816 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003817 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003818 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003819 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003820 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303821 log.Fields{
3822 "newoutport": actionInfo[Output].(uint32),
3823 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003824 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303825 return olterrors.NewErrNotFound("out-port",
3826 log.Fields{
3827 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3828 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003829 }
3830 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3831 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003832 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003833 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003834 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303835 log.Fields{
3836 "newinport": actionInfo[Output].(uint32),
3837 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003838 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303839 return olterrors.NewErrNotFound("nni-port",
3840 log.Fields{
3841 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3842 "in-port": classifierInfo[InPort].(uint32),
3843 "out-port": actionInfo[Output].(uint32),
3844 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003845 }
3846 }
3847 }
3848 return nil
3849}
Gamze Abakafee36392019-10-03 11:17:24 +00003850
Neha Sharma96b7bf22020-06-15 10:37:32 +00003851func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003852 /* Metadata 8 bytes:
3853 Most Significant 2 Bytes = Inner VLAN
3854 Next 2 Bytes = Tech Profile ID(TPID)
3855 Least Significant 4 Bytes = Port ID
3856 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3857 subscriber related flows.
3858 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003859 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003860 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003861 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003862 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003863 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003864 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003865}
3866
3867func appendUnique(slice []uint32, item uint32) []uint32 {
3868 for _, sliceElement := range slice {
3869 if sliceElement == item {
3870 return slice
3871 }
3872 }
3873 return append(slice, item)
3874}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303875
3876// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003877func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303878
3879 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3880 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003881 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003882 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003883 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003884 log.Fields{
3885 "port-number": action[Output].(uint32),
3886 "error": err})
3887 return uint32(0), err
3888 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003889 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303890 return intfID, nil
3891 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003892 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003893 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003894 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003895 log.Fields{
3896 "port-number": action[Output].(uint32),
3897 "error": err})
3898 return uint32(0), err
3899 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003900 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303901 return intfID, nil
3902 }
3903 return uint32(0), nil
3904}
3905
3906// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003907func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3908 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3909 if err != nil {
3910 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3911 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3912 return
3913 }
3914 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003915
3916 f.onuGemInfoLock.Lock()
3917 defer f.onuGemInfoLock.Unlock()
3918
Matt Jeanneret1719a072019-12-20 14:50:14 -05003919 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303920 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003921 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003922 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 +05303923 log.Fields{
3924 "pktinkey": pktInkey,
3925 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003926 return
3927 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303928 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003929 f.packetInGemPort[pktInkey] = gemPort
3930
npujarec5762e2020-01-01 14:08:48 +05303931 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003932 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 +05303933 log.Fields{
3934 "pktinkey": pktInkey,
3935 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303936}
3937
Esin Karaman7fb80c22020-07-16 14:23:33 +00003938//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3939func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3940 if packet == nil || len(packet) < 18 {
3941 log.Error("unable-get-c-tag-from-the-packet--invalid-packet-length ")
3942 return 0, 0, errors.New("invalid packet length")
3943 }
3944 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3945 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3946
3947 var index int8
3948 if outerEthType == 0x8100 {
3949 if innerEthType == 0x8100 {
3950 // q-in-q 802.1ad or 802.1q double tagged packet.
3951 // get the inner vlanId
3952 index = 18
3953 } else {
3954 index = 14
3955 }
3956 priority := (packet[index] >> 5) & 0x7
3957 //13 bits composes vlanId value
3958 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3959 return vlan, priority, nil
3960 }
3961 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3962 return 0, 0, nil
3963}
3964
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303965// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303966func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003967
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003968 f.onuGemInfoLock.Lock()
3969 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003970
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303971 onugem := f.onuGemInfo[intfID]
3972 for idx, onu := range onugem {
3973 if onu.OnuID == onuID {
3974 for _, uni := range onu.UniPorts {
3975 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003976 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 +05303977 return
3978 }
3979 }
3980 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3981 f.onuGemInfo[intfID] = onugem
3982 }
3983 }
npujarec5762e2020-01-01 14:08:48 +05303984 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003985
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303986}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303987
npujarec5762e2020-01-01 14:08:48 +05303988func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3989 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303990 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003991 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303992 return
3993 }
3994 for gem, FlowIDs := range flowIDsList {
3995 gemPK := gemPortKey{intf, uint32(gem)}
Matteo Scandolo738c52a2020-08-03 11:14:22 -07003996 if f.perGemPortLock.TryLock(gemPK) {
3997 f.flowsUsedByGemPort[gemPK] = FlowIDs
3998 f.perGemPortLock.Unlock(gemPK)
3999 } else {
4000 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
4001 log.Fields{
4002 "intf-id": intf,
4003 "device-id": f.deviceHandler.device.Id,
4004 "key": gemPK,
4005 })
4006 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05304007 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05304008}
Esin Karamanccb714b2019-11-29 15:02:06 +00004009
4010//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
4011//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05304012func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
4013 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00004014 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00004015 logger.Error(ctx, "failed-to-get-pon-interface-to-multicast-queue-map")
Esin Karamanccb714b2019-11-29 15:02:06 +00004016 return
4017 }
4018 for intf, queueInfo := range storedMulticastQueueMap {
4019 q := queueInfoBrief{
4020 gemPortID: queueInfo[0],
4021 servicePriority: queueInfo[1],
4022 }
4023 f.interfaceToMcastQueueMap[intf] = &q
4024 }
4025}
4026
4027//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
4028//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
4029//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05304030func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
4031 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00004032 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00004033 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00004034 }
4035 if exists {
4036 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
4037 }
4038 return nil, exists, nil
4039}
4040
4041func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
4042 groupDesc := ofp.OfpGroupDesc{
4043 Type: ofp.OfpGroupType_OFPGT_ALL,
4044 GroupId: groupID,
4045 }
4046 groupEntry := ofp.OfpGroupEntry{
4047 Desc: &groupDesc,
4048 }
Esin Karamanccb714b2019-11-29 15:02:06 +00004049 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00004050 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00004051 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00004052 bucket := ofp.OfpBucket{
4053 Actions: acts,
4054 }
4055 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00004056 }
Esin Karamanccb714b2019-11-29 15:02:06 +00004057 return &groupEntry
4058}