blob: 7fce2f3f72dd1b7c60f4355ac87220ac81a85f1b [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'
manikkaraj kbf256be2019-03-25 00:13:48 +0530176)
177
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400178type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700179 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400180 gemPort uint32
181}
182
Girish Gowdra3d633032019-12-10 16:37:05 +0530183type pendingFlowDeleteKey struct {
184 intfID uint32
185 onuID uint32
186 uniID uint32
187}
188
189type tpLockKey struct {
190 intfID uint32
191 onuID uint32
192 uniID uint32
193}
194
Gamze Abakafee36392019-10-03 11:17:24 +0000195type schedQueue struct {
196 direction tp_pb.Direction
197 intfID uint32
198 onuID uint32
199 uniID uint32
200 tpID uint32
201 uniPort uint32
202 tpInst *tp.TechProfile
203 meterID uint32
204 flowMetadata *voltha.FlowMetadata
205}
206
Esin Karamanccb714b2019-11-29 15:02:06 +0000207type queueInfoBrief struct {
208 gemPortID uint32
209 servicePriority uint32
210}
211
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700212//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530213type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000214 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000215 deviceHandler *DeviceHandler
216 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000217 onuIdsLock sync.RWMutex
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530218 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
219 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
220 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
221 lockCache sync.RWMutex
Girish Gowdra3d633032019-12-10 16:37:05 +0530222 pendingFlowDelete sync.Map
223 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Esin Karamanccb714b2019-11-29 15:02:06 +0000224 perUserFlowHandleLock *mapmutex.Mutex
225 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 +0530226}
227
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700228//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
npujarec5762e2020-01-01 14:08:48 +0530229func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
Shrey Baid26912972020-04-16 21:02:31 +0530230 logger.Infow("initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530231 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530232 var err error
233 var idx uint32
234
manikkaraj kbf256be2019-03-25 00:13:48 +0530235 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530236 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000237 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530238 if err = flowMgr.populateTechProfilePerPonPort(); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530239 logger.Errorw("error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530240 return nil
241 }
William Kurkian740a09c2019-10-23 17:07:38 -0400242 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530243 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
244 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
245 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo)
246 ponPorts := rMgr.DevInfo.GetPonPorts()
247 //Load the onugem info cache from kv store on flowmanager start
248 for idx = 0; idx < ponPorts; idx++ {
npujarec5762e2020-01-01 14:08:48 +0530249 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530250 logger.Error("failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530251 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530252 //Load flowID list per gem map per interface from the kvstore.
npujarec5762e2020-01-01 14:08:48 +0530253 flowMgr.loadFlowIDlistForGem(ctx, idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530254 }
255 flowMgr.lockCache = sync.RWMutex{}
Girish Gowdra3d633032019-12-10 16:37:05 +0530256 flowMgr.pendingFlowDelete = sync.Map{}
Girish Gowdrab77ded92020-04-08 11:45:05 -0700257 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(300, 100000000, 10000000, 1.1, 0.2)
Esin Karamanccb714b2019-11-29 15:02:06 +0000258 flowMgr.interfaceToMcastQueueMap = make(map[uint32]*queueInfoBrief)
259 //load interface to multicast queue map from kv store
npujarec5762e2020-01-01 14:08:48 +0530260 flowMgr.loadInterfaceToMulticastQueueMap(ctx)
Shrey Baid26912972020-04-16 21:02:31 +0530261 logger.Info("initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530262 return &flowMgr
263}
264
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700265func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700266 if direction == Upstream {
Shrey Baid26912972020-04-16 21:02:31 +0530267 logger.Debugw("upstream-flow-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700268 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700269 } else if direction == Downstream {
Shrey Baid26912972020-04-16 21:02:31 +0530270 logger.Debugw("downstream-flow-not-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700271 return uint64(flowID), nil
Esin Karamanccb714b2019-11-29 15:02:06 +0000272 } else if direction == Multicast {
Shrey Baid26912972020-04-16 21:02:31 +0530273 logger.Debugw("multicast-flow-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000274 return 0x2<<15 | uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400275 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530276 return 0, olterrors.NewErrInvalidValue(log.Fields{"direction": direction}, nil).Log()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400277 }
278}
279
npujarec5762e2020-01-01 14:08:48 +0530280func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Shrey Baid26912972020-04-16 21:02:31 +0530281 logger.Debugw("registering-flow-for-device ",
282 log.Fields{
283 "flow": flowFromCore,
284 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000285 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
286 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
287 if !ok {
288 flowIDList = []uint32{deviceFlow.FlowId}
289 }
290 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
291 f.flowsUsedByGemPort[gemPK] = flowIDList
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530292 // update the flowids for a gem to the KVstore
npujarec5762e2020-01-01 14:08:48 +0530293 f.resourceMgr.UpdateFlowIDsForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400294}
295
npujarec5762e2020-01-01 14:08:48 +0530296func (f *OpenOltFlowMgr) divideAndAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000297 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
298 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000299 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530300 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400301 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530302
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700303 logger.Infow("dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530304 "device-id": f.deviceHandler.device.Id,
305 "intf-id": intfID,
306 "onu-id": onuID,
307 "uni-id": uniID,
308 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700309 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530310 "action": actionInfo,
311 "usmeter-iD": UsMeterID,
312 "dsmeter-iD": DsMeterID,
313 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400314 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
315 // is because the flow is an NNI flow and there would be no onu resources associated with it
316 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400317 if onuID <= 0 {
Shrey Baid26912972020-04-16 21:02:31 +0530318 logger.Errorw("no-onu-id-for-flow",
319 log.Fields{
320 "port-no": portNo,
321 "classifer": classifierInfo,
322 "action": actionInfo,
323 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530324 return
325 }
326
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700327 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Shrey Baid26912972020-04-16 21:02:31 +0530328 logger.Debugw("uni-port-path", log.Fields{
329 "uni": uni,
330 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530331
332 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
333 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700334 logger.Debugw("dividing-flow-create-tcont-gem-ports", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530335 "device-id": f.deviceHandler.device.Id,
336 "intf-id": intfID,
337 "onu-id": onuID,
338 "uni-id": uniID,
339 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700340 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530341 "action": actionInfo,
342 "usmeter-id": UsMeterID,
343 "dsmeter-id": DsMeterID,
344 "tp-id": TpID})
npujarec5762e2020-01-01 14:08:48 +0530345 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530346 if allocID == 0 || gemPorts == nil || TpInst == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000347 logger.Error("alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530348 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
349 return
350 }
351 args := make(map[string]uint32)
352 args[IntfID] = intfID
353 args[OnuID] = onuID
354 args[UniID] = uniID
355 args[PortNo] = portNo
356 args[AllocID] = allocID
357
358 /* Flows can be added specific to gemport if p-bits are received.
359 * If no pbit mentioned then adding flows for all gemports
360 */
npujarec5762e2020-01-01 14:08:48 +0530361 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530362 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
363 } else {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700364 logger.Errorw("failed-to-acquire-per-user-flow-handle-lock",
Shrey Baid26912972020-04-16 21:02:31 +0530365 log.Fields{
366 "intf-id": intfID,
367 "onu-id": onuID,
368 "uni-id": uniID,
369 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400370 return
371 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530372}
373
salmansiddiqui7ac62132019-08-22 03:58:50 +0000374// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530375func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400376
Shrey Baid26912972020-04-16 21:02:31 +0530377 logger.Debugw("CreateSchedulerQueues",
378 log.Fields{"dir": sq.direction,
379 "intf-id": sq.intfID,
380 "onu-id": sq.onuID,
381 "uni-id": sq.uniID,
382 "tp-id": sq.tpID,
383 "meter-id": sq.meterID,
384 "tp-inst": sq.tpInst,
385 "flowmetadata": sq.flowMetadata,
386 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400387
Gamze Abakafee36392019-10-03 11:17:24 +0000388 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000389 if err != nil {
390 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400391 }
392
393 /* Lets make a simple assumption that if the meter-id is present on the KV store,
394 * then the scheduler and queues configuration is applied on the OLT device
395 * in the given direction.
396 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000397
Manikkaraj kb1d51442019-07-23 10:41:02 -0400398 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530399 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400400 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530401 return olterrors.NewErrNotFound("meter",
402 log.Fields{"intf-id": sq.intfID,
403 "onu-id": sq.onuID,
404 "uni-id": sq.uniID,
405 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400406 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000407
Manikkaraj kb1d51442019-07-23 10:41:02 -0400408 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000409 if KvStoreMeter.MeterId == sq.meterID {
Shrey Baid26912972020-04-16 21:02:31 +0530410 logger.Debugw("scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400411 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400412 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530413 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800414 "unsupported": "meter-id",
415 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530416 "meter-id-in-flow": sq.meterID,
417 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400418 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000419
Shrey Baid26912972020-04-16 21:02:31 +0530420 logger.Debugw("meter-does-not-exist-creating-new",
421 log.Fields{
422 "meter-id": sq.meterID,
423 "direction": Direction,
424 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000425
Gamze Abakafee36392019-10-03 11:17:24 +0000426 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000427 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Gamze Abakafee36392019-10-03 11:17:24 +0000428 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000429 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400430 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000431
432 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530433 return olterrors.NewErrNotFound("scheduler-config",
434 log.Fields{
435 "intf-id": sq.intfID,
436 "direction": sq.direction,
437 "tp-inst": sq.tpInst,
438 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000439 }
440
Manikkaraj kb1d51442019-07-23 10:41:02 -0400441 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000442 if sq.flowMetadata != nil {
443 for _, meter := range sq.flowMetadata.Meters {
444 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400445 meterConfig = meter
Shrey Baid26912972020-04-16 21:02:31 +0530446 logger.Debugw("found-meter-config-from-flowmetadata",
447 log.Fields{"meterConfig": meterConfig,
448 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400449 break
450 }
451 }
452 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530453 logger.Errorw("flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400454 }
455 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530456 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800457 "reason": "Could-not-get-meterbands-from-flowMetadata",
458 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530459 "meter-id": sq.meterID,
460 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400461 } else if len(meterConfig.Bands) < MaxMeterBand {
Shrey Baid26912972020-04-16 21:02:31 +0530462 logger.Errorw("invalid-number-of-bands-in-meter",
463 log.Fields{"Bands": meterConfig.Bands,
464 "meter-id": sq.meterID,
465 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530466 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800467 "reason": "Invalid-number-of-bands-in-meter",
468 "meterband-count": len(meterConfig.Bands),
469 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530470 "meter-id": sq.meterID,
471 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400472 }
473 cir := meterConfig.Bands[0].Rate
474 cbs := meterConfig.Bands[0].BurstSize
475 eir := meterConfig.Bands[1].Rate
476 ebs := meterConfig.Bands[1].BurstSize
477 pir := cir + eir
478 pbs := cbs + ebs
479 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
480
Gamze Abakafee36392019-10-03 11:17:24 +0000481 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000482 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400483
npujarec5762e2020-01-01 14:08:48 +0530484 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530485 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
486 log.Fields{"intf-id": sq.intfID,
487 "direction": sq.direction,
488 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400489 }
490
salmansiddiqui7ac62132019-08-22 03:58:50 +0000491 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400492 * store the meter id on the KV store, for further reference.
493 */
npujarec5762e2020-01-01 14:08:48 +0530494 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 +0530495 return olterrors.NewErrAdapter("failed-updating-meter-id",
496 log.Fields{"onu-id": sq.onuID,
497 "meter-id": sq.meterID,
498 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400499 }
Shrey Baid26912972020-04-16 21:02:31 +0530500 logger.Infow("updated-meter-info-into-kv-store-successfully",
501 log.Fields{"direction": Direction,
502 "Meter": meterConfig,
503 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400504 return nil
505}
506
npujarec5762e2020-01-01 14:08:48 +0530507func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000508
509 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
510
511 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530512 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
513 log.Fields{"intf-id": sq.intfID,
514 "direction": sq.direction,
515 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000516 }
517
Shrey Baid26912972020-04-16 21:02:31 +0530518 logger.Debugw("sending-traffic-scheduler-create-to-device",
519 log.Fields{
520 "direction": sq.direction,
521 "TrafficScheds": TrafficSched,
522 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530523 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000524 IntfId: sq.intfID, OnuId: sq.onuID,
525 UniId: sq.uniID, PortNo: sq.uniPort,
526 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000527 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000528 }
Shrey Baid26912972020-04-16 21:02:31 +0530529 logger.Infow("successfully-created-traffic-schedulers", log.Fields{
530 "direction": sq.direction,
531 "traffic-queues": trafficQueues,
532 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000533
534 // On receiving the CreateTrafficQueues request, the driver should create corresponding
535 // downstream queues.
Shrey Baid26912972020-04-16 21:02:31 +0530536 logger.Debugw("sending-traffic-queues-create-to-device",
537 log.Fields{"direction": sq.direction,
538 "traffic-queues": trafficQueues,
539 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530540 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000541 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
542 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000543 TrafficQueues: trafficQueues,
544 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530545 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000546 }
Shrey Baid26912972020-04-16 21:02:31 +0530547 logger.Infow("successfully-created-traffic-schedulers", log.Fields{
548 "direction": sq.direction,
549 "traffic-queues": trafficQueues,
550 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000551
Esin Karamanccb714b2019-11-29 15:02:06 +0000552 if sq.direction == tp_pb.Direction_DOWNSTREAM {
553 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(sq.tpInst)
554 if len(multicastTrafficQueues) > 0 {
555 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
556 //assumed that there is only one queue per PON for the multicast service
557 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
558 //just put it in interfaceToMcastQueueMap to use for building group members
Shrey Baid26912972020-04-16 21:02:31 +0530559 logger.Debugw("multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000560 multicastQueuePerPonPort := multicastTrafficQueues[0]
561 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
562 gemPortID: multicastQueuePerPonPort.GemportId,
563 servicePriority: multicastQueuePerPonPort.Priority,
564 }
565 //also store the queue info in kv store
npujarec5762e2020-01-01 14:08:48 +0530566 f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID,
Esin Karamanccb714b2019-11-29 15:02:06 +0000567 multicastQueuePerPonPort.GemportId,
568 multicastQueuePerPonPort.Priority)
Shrey Baid26912972020-04-16 21:02:31 +0530569
570 logger.Infow("multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000571 }
572 }
573 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000574 return nil
575}
576
salmansiddiqui7ac62132019-08-22 03:58:50 +0000577// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530578func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400579
580 var Direction string
581 var SchedCfg *tp_pb.SchedulerConfig
582 var err error
Shrey Baid26912972020-04-16 21:02:31 +0530583 logger.Infow("removing-schedulers-and-queues-in-olt",
584 log.Fields{
585 "direction": sq.direction,
586 "intf-id": sq.intfID,
587 "onu-id": sq.onuID,
588 "uni-id": sq.uniID,
589 "uni-port": sq.uniPort,
590 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000591 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000592 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400593 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000594 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000595 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400596 Direction = "downstream"
597 }
598
Girish Kumar8f73fe02019-12-09 13:19:37 +0000599 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530600 return olterrors.NewErrNotFound("scheduler-config",
601 log.Fields{
602 "int-id": sq.intfID,
603 "direction": sq.direction,
604 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000605 }
606
npujarec5762e2020-01-01 14:08:48 +0530607 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400608 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530609 return olterrors.NewErrNotFound("meter",
610 log.Fields{
611 "onu-id": sq.onuID,
612 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400613 }
614 if KVStoreMeter == nil {
Shrey Baid26912972020-04-16 21:02:31 +0530615 logger.Warnw("no-meter-installed-yet",
616 log.Fields{
617 "direction": Direction,
618 "intf-id": sq.intfID,
619 "onu-id": sq.onuID,
620 "uni-id": sq.uniID,
621 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400622 return nil
623 }
624 cir := KVStoreMeter.Bands[0].Rate
625 cbs := KVStoreMeter.Bands[0].BurstSize
626 eir := KVStoreMeter.Bands[1].Rate
627 ebs := KVStoreMeter.Bands[1].BurstSize
628 pir := cir + eir
629 pbs := cbs + ebs
630
631 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
632
Gamze Abakafee36392019-10-03 11:17:24 +0000633 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000634 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000635
636 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
637 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530638 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
639 log.Fields{
640 "intf-id": sq.intfID,
641 "direction": sq.direction,
642 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000643 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400644
npujarec5762e2020-01-01 14:08:48 +0530645 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000646 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
647 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000648 TrafficQueues: TrafficQueues,
649 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000650 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530651 log.Fields{
652 "intf-id": sq.intfID,
653 "traffic-queues": TrafficQueues,
654 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400655 }
Shrey Baid26912972020-04-16 21:02:31 +0530656 logger.Infow("removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530657 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000658 IntfId: sq.intfID, OnuId: sq.onuID,
659 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400660 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000661 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530662 log.Fields{
663 "intf-id": sq.intfID,
664 "traffic-schedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400665 }
666
Shrey Baid26912972020-04-16 21:02:31 +0530667 logger.Infow("removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000668
669 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400670 * delete the meter id on the KV store.
671 */
npujarec5762e2020-01-01 14:08:48 +0530672 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400673 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530674 return olterrors.NewErrAdapter("unable-to-remove-meter",
675 log.Fields{
676 "onu": sq.onuID,
677 "meter": KVStoreMeter.MeterId,
678 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400679 }
Shrey Baid26912972020-04-16 21:02:31 +0530680 logger.Infow("removed-meter-from-KV-store-successfully",
681 log.Fields{
682 "meter-id": KVStoreMeter.MeterId,
683 "dir": Direction,
684 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400685 return err
686}
687
Gamze Abakafee36392019-10-03 11:17:24 +0000688// This function allocates tconts and GEM ports for an ONU
npujarec5762e2020-01-01 14:08:48 +0530689func (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, *tp.TechProfile) {
Gamze Abakafee36392019-10-03 11:17:24 +0000690 var allocIDs []uint32
691 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530692 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530693 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000694 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000695
npujarec5762e2020-01-01 14:08:48 +0530696 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
697 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400698
699 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530700
Shrey Baid26912972020-04-16 21:02:31 +0530701 logger.Debugw("creating-new-tcont-and-gem", log.Fields{
702 "intf-id": intfID,
703 "onu-id": onuID,
704 "uni-id": uniID,
705 "device-id": f.deviceHandler.device.Id,
706 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530707
Manikkaraj kb1d51442019-07-23 10:41:02 -0400708 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530709 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000710 if techProfileInstance == nil {
Shrey Baid26912972020-04-16 21:02:31 +0530711 logger.Infow("tp-instance-not-found--creating-new",
712 log.Fields{
713 "path": tpPath,
714 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530715 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000716 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530717 // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +0530718 logger.Errorw("tp-instance-create-failed",
719 log.Fields{
720 "error": err,
721 "tp-id": TpID,
722 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000723 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530724 }
npujarec5762e2020-01-01 14:08:48 +0530725 f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530726 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530727 logger.Debugw("tech-profile-instance-already-exist-for-given port-name",
728 log.Fields{
729 "uni": uni,
730 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530731 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530732 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400733 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000734 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
735 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530736 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530737 logger.Errorw("CreateSchedulerQueues-failed-upstream",
738 log.Fields{
739 "error": err,
740 "meter-id": UsMeterID,
741 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000742 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400743 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530744 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400745 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000746 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
747 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530748 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530749 logger.Errorw("CreateSchedulerQueues-failed-downstream",
750 log.Fields{
751 "error": err,
752 "meter-id": DsMeterID,
753 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000754 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400755 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530756 }
Gamze Abakafee36392019-10-03 11:17:24 +0000757
758 allocID := techProfileInstance.UsScheduler.AllocID
Gamze Abakafee36392019-10-03 11:17:24 +0000759 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Gamze Abakafee36392019-10-03 11:17:24 +0000760 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400761 }
Gamze Abakafee36392019-10-03 11:17:24 +0000762
Girish Gowdra3d633032019-12-10 16:37:05 +0530763 if tpInstanceExists {
764 return allocID, gemPortIDs, techProfileInstance
765 }
766
767 allocIDs = appendUnique(allocIDs, allocID)
768 for _, gemPortID := range gemPortIDs {
769 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
770 }
771
Shrey Baid26912972020-04-16 21:02:31 +0530772 logger.Infow("allocated-tcont-and-gem-ports",
773 log.Fields{
774 "alloc-ids": allocIDs,
775 "gemports": allgemPortIDs,
776 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530777 // Send Tconts and GEM ports to KV store
npujarec5762e2020-01-01 14:08:48 +0530778 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000779 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530780}
781
npujarec5762e2020-01-01 14:08:48 +0530782func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530783
Shrey Baid26912972020-04-16 21:02:31 +0530784 logger.Debugw("storing-allocated-tconts-and-gem-ports-into-KV-store",
785 log.Fields{
786 "intf-id": intfID,
787 "onu-id": onuID,
788 "uni-id": uniID,
789 "alloc-id": allocID,
790 "gemport-ids": gemPortIDs,
791 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530792 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530793 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530794 logger.Errorw("error-while-uploading-allocid-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530795 }
npujarec5762e2020-01-01 14:08:48 +0530796 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530797 logger.Errorw("error-while-uploading-gemports-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530798 }
npujarec5762e2020-01-01 14:08:48 +0530799 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530800 logger.Error("error-while-uploading-gemtopon-map-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530801 }
Shrey Baid26912972020-04-16 21:02:31 +0530802 logger.Infow("stored-tconts-and-gem-into-kv-store-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400803 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530804 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400805 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530806}
807
808func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000809 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530810 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000811 for _, intfID := range techRange.IntfIds {
812 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400813 tpCount++
Shrey Baid26912972020-04-16 21:02:31 +0530814 logger.Debugw("init-tech-profile-done",
815 log.Fields{
816 "intf-id": intfID,
817 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530818 }
819 }
820 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400821 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530822 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530823 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800824 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530825 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
826 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530827 }
Shrey Baid26912972020-04-16 21:02:31 +0530828 logger.Infow("populated-techprofile-for-ponports-successfully",
829 log.Fields{
830 "numofTech": tpCount,
831 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
832 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530833 return nil
834}
835
npujarec5762e2020-01-01 14:08:48 +0530836func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530837 portNo uint32, uplinkClassifier map[string]interface{},
838 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000839 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700840 uplinkClassifier[PacketTagType] = SingleTag
Shrey Baid26912972020-04-16 21:02:31 +0530841 logger.Debugw("adding-upstream-data-flow",
842 log.Fields{
843 "uplinkClassifier": uplinkClassifier,
844 "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800845 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000846 Upstream, logicalFlow, allocID, gemportID, tpID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530847 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530848}
849
npujarec5762e2020-01-01 14:08:48 +0530850func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530851 portNo uint32, downlinkClassifier map[string]interface{},
852 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000853 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700854 downlinkClassifier[PacketTagType] = DoubleTag
Shrey Baid26912972020-04-16 21:02:31 +0530855 logger.Debugw("adding-downstream-data-flow",
856 log.Fields{
857 "downlinkClassifier": downlinkClassifier,
858 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400859 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
860 if vlan, exists := downlinkClassifier[VlanVid]; exists {
861 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700862 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400863 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
Shrey Baid26912972020-04-16 21:02:31 +0530864 logger.Infow("ignoring-dl-trap-device-flow-from-core",
865 log.Fields{
866 "flow": logicalFlow,
867 "device-id": f.deviceHandler.device.Id,
868 "onu-id": onuID,
869 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800870 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400871 }
872 }
873 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530874 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400875
Manikkaraj k884c1242019-04-11 16:26:42 +0530876 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700877 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400878 // vlan_vid is a uint32. must be type asserted as such or conversion fails
879 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530880 if ok {
881 downlinkAction[VlanVid] = dlClVid & 0xfff
882 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530883 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530884 "reason": "failed-to-convert-vlanid-classifier",
885 "vlan-id": VlanVid,
886 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530887 }
888
David K. Bainbridge794735f2020-02-11 21:01:37 -0800889 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000890 Downstream, logicalFlow, allocID, gemportID, tpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530891}
892
npujarec5762e2020-01-01 14:08:48 +0530893func (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 +0530894 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000895 allocID uint32, gemPortID uint32, tpID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530896 /* One of the OLT platform (Broadcom BAL) requires that symmetric
897 flows require the same flow_id to be used across UL and DL.
898 Since HSIA flow is the only symmetric flow currently, we need to
899 re-use the flow_id across both direction. The 'flow_category'
900 takes priority over flow_cookie to find any available HSIA_FLOW
901 id for the ONU.
902 */
Shrey Baid26912972020-04-16 21:02:31 +0530903 logger.Infow("adding-hsia-flow",
904 log.Fields{
905 "intf-id": intfID,
906 "onu-id": onuID,
907 "uni-id": uniID,
908 "device-id": f.deviceHandler.device.Id,
909 "classifier": classifier,
910 "action": action,
911 "direction": direction,
912 "alloc-id": allocID,
913 "gemport-id": gemPortID,
914 "logicalflow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530915 var vlanPbit uint32 = 0xff // means no pbit
Gamze Abaka724d0852020-03-18 12:10:24 +0000916 var vlanVid uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400917 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000918 vlanPbit = classifier[VlanPcp].(uint32)
Shrey Baid26912972020-04-16 21:02:31 +0530919 logger.Debugw("found-pbit-in-flow",
920 log.Fields{
921 "vlan-pbit": vlanPbit,
922 "intf-id": intfID,
923 "onu-id": onuID,
924 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800925 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530926 logger.Debugw("pbit-not-found-in-flow",
927 log.Fields{
928 "vlan-pcp": VlanPcp,
929 "intf-id": intfID,
930 "onu-id": onuID,
931 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400932 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000933 if _, ok := classifier[VlanVid]; ok {
934 vlanVid = classifier[VlanVid].(uint32)
Shrey Baid26912972020-04-16 21:02:31 +0530935 log.Debugw("found-vlan-in-the-flow",
936 log.Fields{
937 "vlan-vid": vlanVid,
938 "intf-id": intfID,
939 "onu-id": onuID,
940 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000941 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700942 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530943 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +0530944 logger.Infow("flow-already-exists",
945 log.Fields{
946 "device-id": f.deviceHandler.device.Id,
947 "intf-id": intfID,
948 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800949 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530950 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000951 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530952 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530953 return olterrors.NewErrNotFound("hsia-flow-id",
954 log.Fields{
955 "direction": direction,
956 "device-id": f.deviceHandler.device.Id,
957 "intf-id": intfID,
958 "onu-id": onuID,
959 }, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530960 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800961 classifierProto, err := makeOpenOltClassifierField(classifier)
962 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530963 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530964 }
Shrey Baid26912972020-04-16 21:02:31 +0530965 logger.Debugw("created-classifier-proto",
966 log.Fields{
967 "classifier": *classifierProto,
968 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000969 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800970 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530971 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530972 }
Shrey Baid26912972020-04-16 21:02:31 +0530973 logger.Debugw("created-action-proto",
974 log.Fields{
975 "action": *actionProto,
976 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800977 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530978 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530979 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800980 log.Fields{
981 "classifier": classifier,
982 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +0530983 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800984 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530985 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700986 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
987 OnuId: int32(onuID),
988 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000989 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530990 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700991 AllocId: int32(allocID),
992 NetworkIntfId: int32(networkIntfID),
993 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530994 Classifier: classifierProto,
995 Action: actionProto,
996 Priority: int32(logicalFlow.Priority),
997 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000998 PortNo: portNo,
999 TechProfileId: tpID,
1000 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001001 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301002 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301003 }
Shrey Baid26912972020-04-16 21:02:31 +05301004 logger.Infow("hsia-flow-added-to-device-successfully",
1005 log.Fields{"direction": direction,
1006 "device-id": f.deviceHandler.device.Id,
1007 "flow": flow,
1008 "intf-id": intfID,
1009 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001010 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
1011 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1012 flow.OnuId,
1013 flow.UniId,
1014 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301015 return olterrors.NewErrPersistence("update", "flow", flowID,
1016 log.Fields{
1017 "flow": flow,
1018 "device-id": f.deviceHandler.device.Id,
1019 "intf-id": intfID,
1020 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001021 }
1022 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301023}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001024
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001025func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1026 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1027 gemPortID uint32, tpID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301028
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301029 networkIntfID, err := getNniIntfID(classifier, action)
1030 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301031 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001032 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301033 "action": action,
1034 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001035 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301036 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301037
1038 // Clear the action map
1039 for k := range action {
1040 delete(action, k)
1041 }
1042
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001043 action[TrapToHost] = true
1044 classifier[UDPSrc] = uint32(68)
1045 classifier[UDPDst] = uint32(67)
1046 classifier[PacketTagType] = SingleTag
1047 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301048
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001049 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301050 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301051 logger.Infow("flow-exists--not-re-adding",
1052 log.Fields{
1053 "device-id": f.deviceHandler.device.Id,
1054 "intf-id": intfID,
1055 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001056 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301057 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301058
David K. Bainbridge794735f2020-02-11 21:01:37 -08001059 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 +05301060
1061 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301062 return olterrors.NewErrNotFound("flow",
1063 log.Fields{
1064 "interface-id": intfID,
1065 "gem-port": gemPortID,
1066 "cookie": flowStoreCookie,
1067 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001068 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301069 }
1070
Shrey Baid26912972020-04-16 21:02:31 +05301071 logger.Debugw("creating-ul-dhcp-flow",
1072 log.Fields{
1073 "ul_classifier": classifier,
1074 "ul_action": action,
1075 "uplinkFlowId": flowID,
1076 "intf-id": intfID,
1077 "onu-id": onuID,
1078 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301079
David K. Bainbridge794735f2020-02-11 21:01:37 -08001080 classifierProto, err := makeOpenOltClassifierField(classifier)
1081 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301082 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301083 }
Shrey Baid26912972020-04-16 21:02:31 +05301084 logger.Debugw("created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001085 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001086 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301087 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301088 }
1089
David K. Bainbridge794735f2020-02-11 21:01:37 -08001090 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001091 OnuId: int32(onuID),
1092 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301093 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001094 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001095 AllocId: int32(allocID),
1096 NetworkIntfId: int32(networkIntfID),
1097 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301098 Classifier: classifierProto,
1099 Action: actionProto,
1100 Priority: int32(logicalFlow.Priority),
1101 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001102 PortNo: portNo,
1103 TechProfileId: tpID,
1104 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001105 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301106 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001107 }
Shrey Baid26912972020-04-16 21:02:31 +05301108 logger.Infow("dhcp-ul-flow-added-to-device-successfully",
1109 log.Fields{
1110 "device-id": f.deviceHandler.device.Id,
1111 "flow-id": flowID,
1112 "intf-id": intfID,
1113 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001114 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
1115 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
1116 dhcpFlow.OnuId,
1117 dhcpFlow.UniId,
1118 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301119 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1120 log.Fields{
1121 "flow": dhcpFlow,
1122 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301123 }
1124
David K. Bainbridge794735f2020-02-11 21:01:37 -08001125 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301126}
1127
Esin Karamanae41e2b2019-12-17 18:13:13 +00001128//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301129func (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 +00001130 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32) error {
1131 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001132}
1133
1134//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301135func (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 +00001136 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string, tpID uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001137
1138 networkIntfID, err := getNniIntfID(classifier, action)
1139 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301140 return olterrors.NewErrNotFound("nni-interface-id",
1141 log.Fields{
1142 "classifier": classifier,
1143 "action": action,
1144 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001145 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001146 }
1147
1148 // Clear the action map
1149 for k := range action {
1150 delete(action, k)
1151 }
1152
1153 action[TrapToHost] = true
1154 classifier[PacketTagType] = SingleTag
1155 delete(classifier, VlanVid)
1156
1157 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301158 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301159 logger.Infow("flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001160 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001161 }
1162
npujarec5762e2020-01-01 14:08:48 +05301163 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 +00001164
1165 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301166 return olterrors.NewErrNotFound("flow-id",
1167 log.Fields{
1168 "intf-id": intfID,
1169 "oni-id": onuID,
1170 "cookie": flowStoreCookie,
1171 "flow-type": flowType,
1172 "device-id": f.deviceHandler.device.Id,
1173 "onu-id": onuID},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001174 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001175 }
1176
Shrey Baid26912972020-04-16 21:02:31 +05301177 logger.Debugw("creating-upstream-trap-flow",
1178 log.Fields{
1179 "ul_classifier": classifier,
1180 "ul_action": action,
1181 "uplinkFlowId": flowID,
1182 "flowType": flowType,
1183 "device-id": f.deviceHandler.device.Id,
1184 "intf-id": intfID,
1185 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001186
David K. Bainbridge794735f2020-02-11 21:01:37 -08001187 classifierProto, err := makeOpenOltClassifierField(classifier)
1188 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301189 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001190 }
Shrey Baid26912972020-04-16 21:02:31 +05301191 logger.Debugw("created-classifier-proto",
1192 log.Fields{
1193 "classifier": *classifierProto,
1194 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001195 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001196 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301197 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001198 }
1199
David K. Bainbridge794735f2020-02-11 21:01:37 -08001200 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001201 OnuId: int32(onuID),
1202 UniId: int32(uniID),
1203 FlowId: flowID,
1204 FlowType: Upstream,
1205 AllocId: int32(allocID),
1206 NetworkIntfId: int32(networkIntfID),
1207 GemportId: int32(gemPortID),
1208 Classifier: classifierProto,
1209 Action: actionProto,
1210 Priority: int32(logicalFlow.Priority),
1211 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001212 PortNo: portNo,
1213 TechProfileId: tpID,
1214 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001215
David K. Bainbridge794735f2020-02-11 21:01:37 -08001216 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301217 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 -08001218 }
Shrey Baid26912972020-04-16 21:02:31 +05301219 logger.Infof("%s ul-flow-added-to-device-successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001220
David K. Bainbridge794735f2020-02-11 21:01:37 -08001221 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
1222 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1223 flow.OnuId,
1224 flow.UniId,
1225 flow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301226 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 +00001227 }
1228
David K. Bainbridge794735f2020-02-11 21:01:37 -08001229 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001230}
1231
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001232// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001233func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1234 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1235 gemPortID uint32, vlanID uint32, tpID uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05301236 logger.Infow("adding-eapol-to-device",
1237 log.Fields{
1238 "intf-id": intfID,
1239 "onu-id": onuID,
1240 "port-no": portNo,
1241 "alloc-id": allocID,
1242 "gemport-id": gemPortID,
1243 "vlan-id": vlanID,
1244 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301245
1246 uplinkClassifier := make(map[string]interface{})
1247 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301248
manikkaraj kbf256be2019-03-25 00:13:48 +05301249 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001250 uplinkClassifier[EthType] = uint32(EapEthType)
1251 uplinkClassifier[PacketTagType] = SingleTag
1252 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001253 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301254 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001255 uplinkAction[TrapToHost] = true
1256 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301257 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301258 logger.Infow("flow-exists-not-re-adding", log.Fields{
1259 "device-id": f.deviceHandler.device.Id,
1260 "onu-id": onuID,
1261 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001262 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301263 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301264 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +00001265 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +05301266 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301267 return olterrors.NewErrNotFound("flow-id",
1268 log.Fields{
1269 "intf-id": intfID,
1270 "onu-id": onuID,
1271 "coookie": flowStoreCookie,
1272 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001273 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301274 }
Shrey Baid26912972020-04-16 21:02:31 +05301275 logger.Debugw("creating-ul-eapol-flow",
1276 log.Fields{
1277 "ul_classifier": uplinkClassifier,
1278 "ul_action": uplinkAction,
1279 "uplinkFlowId": uplinkFlowID,
1280 "device-id": f.deviceHandler.device.Id,
1281 "intf-id": intfID,
1282 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301283
David K. Bainbridge794735f2020-02-11 21:01:37 -08001284 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1285 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301286 return olterrors.NewErrInvalidValue(log.Fields{
1287 "classifier": uplinkClassifier,
1288 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301289 }
Shrey Baid26912972020-04-16 21:02:31 +05301290 logger.Debugw("created-classifier-proto",
1291 log.Fields{
1292 "classifier": *classifierProto,
1293 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001294 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001295 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301296 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301297 }
Shrey Baid26912972020-04-16 21:02:31 +05301298 logger.Debugw("created-action-proto",
1299 log.Fields{
1300 "action": *actionProto,
1301 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001302 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301303 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301304 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001305 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301306 "action": action,
1307 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001308 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301309 }
1310
David K. Bainbridge794735f2020-02-11 21:01:37 -08001311 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001312 OnuId: int32(onuID),
1313 UniId: int32(uniID),
1314 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001315 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001316 AllocId: int32(allocID),
1317 NetworkIntfId: int32(networkIntfID),
1318 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301319 Classifier: classifierProto,
1320 Action: actionProto,
1321 Priority: int32(logicalFlow.Priority),
1322 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001323 PortNo: portNo,
1324 TechProfileId: tpID,
1325 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001326 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301327 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001328 }
Shrey Baid26912972020-04-16 21:02:31 +05301329 logger.Infow("eapol-ul-flow-added-to-device-successfully",
1330 log.Fields{
1331 "device-id": f.deviceHandler.device.Id,
1332 "onu-id": onuID,
1333 "intf-id": intfID,
1334 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001335 flowCategory := "EAPOL"
1336 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1337 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1338 upstreamFlow.OnuId,
1339 upstreamFlow.UniId,
1340 upstreamFlow.FlowId,
1341 /* lowCategory, */
1342 flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301343 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1344 log.Fields{
1345 "flow": upstreamFlow,
1346 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301347 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001348 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301349}
1350
David K. Bainbridge794735f2020-02-11 21:01:37 -08001351func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001352 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001353
1354 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1355 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1356 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001357 if vlanID != ReservedVlan {
1358 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001359 classifier.OVid = vid
1360 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301361 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001362 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1363 vid := uint32(metadata)
1364 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001365 classifier.IVid = vid
1366 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301367 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301368 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001369 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301370 classifier.OPbits = vlanPcp
1371 } else {
1372 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301373 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001374 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1375 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1376 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1377 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001378 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001379 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1380 classifier.PktTagType = pktTagType
1381
1382 switch pktTagType {
1383 case SingleTag:
1384 case DoubleTag:
1385 case Untagged:
1386 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001387 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301388 }
1389 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001390 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301391}
1392
Gamze Abaka724d0852020-03-18 12:10:24 +00001393func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001394 var actionCmd openoltpb2.ActionCmd
1395 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301396 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001397 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301398 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001399 if _, ok := actionInfo[VlanPcp]; ok {
1400 action.Cmd.RemarkInnerPbits = true
1401 action.IPbits = actionInfo[VlanPcp].(uint32)
1402 if _, ok := actionInfo[VlanVid]; ok {
1403 action.Cmd.TranslateInnerTag = true
1404 action.IVid = actionInfo[VlanVid].(uint32)
1405 }
1406 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001407 } else if _, ok := actionInfo[PushVlan]; ok {
1408 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301409 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001410 if _, ok := actionInfo[VlanPcp]; ok {
1411 action.OPbits = actionInfo[VlanPcp].(uint32)
1412 action.Cmd.RemarkOuterPbits = true
1413 if _, ok := classifierInfo[VlanVid]; ok {
1414 action.IVid = classifierInfo[VlanVid].(uint32)
1415 action.Cmd.TranslateInnerTag = true
1416 }
1417 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001418 } else if _, ok := actionInfo[TrapToHost]; ok {
1419 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301420 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001421 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301422 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001423 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301424}
1425
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001426// getTPpath return the ETCD path for a given UNI port
1427func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uniPath string, TpID uint32) string {
1428 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301429}
1430
Gamze Abakafee36392019-10-03 11:17:24 +00001431// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301432func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1433 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001434 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1435
Gamze Abakafee36392019-10-03 11:17:24 +00001436 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301437 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301438 olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301439 // return err
1440 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001441 }
Shrey Baid26912972020-04-16 21:02:31 +05301442 log.Debugw("tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001443 }
1444 return nil
1445}
1446
1447// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301448func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001449 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001450 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001451 }
npujarec5762e2020-01-01 14:08:48 +05301452 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301453 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1454 log.Fields{
1455 "tp-id": tpID,
1456 "uni-port-name": uniPortName,
1457 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001458 }
1459 return nil
1460}
1461
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001462func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301463 if len(classifier) == 0 { // should never happen
Shrey Baid26912972020-04-16 21:02:31 +05301464 logger.Error("invalid-classfier-object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301465 return 0
1466 }
Shrey Baid26912972020-04-16 21:02:31 +05301467 logger.Debugw("generating-flow-store-cookie",
1468 log.Fields{
1469 "classifier": classifier,
1470 "gemport-id": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301471 var jsonData []byte
1472 var flowString string
1473 var err error
1474 // TODO: Do we need to marshall ??
1475 if jsonData, err = json.Marshal(classifier); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301476 logger.Error("failed-to-encode-classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301477 return 0
1478 }
1479 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001480 if gemPortID != 0 {
1481 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301482 }
1483 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001484 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301485 hash := big.NewInt(0)
1486 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301487 generatedHash := hash.Uint64()
Shrey Baid26912972020-04-16 21:02:31 +05301488 logger.Debugw("hash-generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301489 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301490}
1491
npujarec5762e2020-01-01 14:08:48 +05301492func (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 +05301493 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001494 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001495 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1496 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1497 */
1498 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001499 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001500 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001501 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001502 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001503 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301504 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001505 if existingFlows != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301506 logger.Debugw("flow-exists-for-given-flowID--appending-it-to-current-flow",
1507 log.Fields{
1508 "flow-id": flow.FlowId,
1509 "device-id": f.deviceHandler.device.Id,
1510 "intf-id": intfID,
1511 "onu-id": flow.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001512 //for _, f := range *existingFlows {
1513 // flows = append(flows, f)
1514 //}
1515 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001516 }
Shrey Baid26912972020-04-16 21:02:31 +05301517 logger.Debugw("updated-flows-for-given-flowID-and-onuid",
1518 log.Fields{
1519 "updatedflow": flows,
1520 "flow-id": flow.FlowId,
1521 "onu-id": flow.OnuId,
1522 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +05301523 return &flows
1524}
1525
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001526//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1527// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1528// var intfId uint32
1529// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1530// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1531// */
1532// if flow.AccessIntfId != -1 {
1533// intfId = uint32(flow.AccessIntfId)
1534// } else {
1535// intfId = uint32(flow.NetworkIntfId)
1536// }
1537// // Get existing flows matching flowid for given subscriber from KV store
1538// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1539// if existingFlows != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001540// logger.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001541// for _, f := range *existingFlows {
1542// flows = append(flows, f)
1543// }
1544// }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001545// logger.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001546// return &flows
1547//}
1548
npujarec5762e2020-01-01 14:08:48 +05301549func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(ctx context.Context, intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
Shrey Baid26912972020-04-16 21:02:31 +05301550 logger.Debugw("storing-flow(s)-into-kv-store", log.Fields{
1551 "flow-id": flowID,
1552 "device-id": f.deviceHandler.device.Id,
1553 "intf-id": intfID,
1554 "onu-id": onuID})
npujarec5762e2020-01-01 14:08:48 +05301555 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301556 logger.Warnw("error-while-storing-flow-into-kv-store", log.Fields{
1557 "device-id": f.deviceHandler.device.Id,
1558 "onu-id": onuID,
1559 "intf-id": intfID,
1560 "flow-id": flowID})
manikkaraj k17652a72019-05-06 09:06:36 -04001561 return err
1562 }
Shrey Baid26912972020-04-16 21:02:31 +05301563 logger.Infow("stored-flow(s)-into-kv-store-successfully!", log.Fields{
1564 "device-id": f.deviceHandler.device.Id,
1565 "onu-id": onuID,
1566 "intf-id": intfID,
1567 "flow-id": flowID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301568 return nil
1569}
1570
David K. Bainbridge794735f2020-02-11 21:01:37 -08001571func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001572
1573 var intfID uint32
1574 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1575 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1576 */
1577 if deviceFlow.AccessIntfId != -1 {
1578 intfID = uint32(deviceFlow.AccessIntfId)
1579 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001580 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001581 intfID = uint32(deviceFlow.NetworkIntfId)
1582 }
1583
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001584 logger.Debugw("sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301585 "flow": *deviceFlow,
1586 "device-id": f.deviceHandler.device.Id,
1587 "intf-id": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301588 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001589
1590 st, _ := status.FromError(err)
1591 if st.Code() == codes.AlreadyExists {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001592 logger.Debug("flow-already-exists", log.Fields{
1593 "err": err,
1594 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301595 "device-id": f.deviceHandler.device.Id,
1596 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001597 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301598 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001599
1600 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301601 logger.Errorw("failed-to-add-flow-to-device",
1602 log.Fields{"err": err,
1603 "device-flow": deviceFlow,
1604 "device-id": f.deviceHandler.device.Id,
1605 "intf-id": intfID})
npujarec5762e2020-01-01 14:08:48 +05301606 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001607 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001608 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301609 if deviceFlow.GemportId != -1 {
1610 // No need to register the flow if it is a trap on nni flow.
npujarec5762e2020-01-01 14:08:48 +05301611 f.registerFlow(ctx, logicalFlow, deviceFlow)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301612 }
Shrey Baid26912972020-04-16 21:02:31 +05301613 logger.Infow("flow-added-to-device-successfully ",
1614 log.Fields{
1615 "flow": *deviceFlow,
1616 "device-id": f.deviceHandler.device.Id,
1617 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001618 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001619}
1620
David K. Bainbridge794735f2020-02-11 21:01:37 -08001621func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) error {
Shrey Baid26912972020-04-16 21:02:31 +05301622 logger.Debugw("sending-flow-to-device-via-grpc",
1623 log.Fields{
1624 "flow": *deviceFlow,
1625 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001626 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1627 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001628 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Shrey Baid26912972020-04-16 21:02:31 +05301629 logger.Warnw("can-not-remove-flow-from-device--unreachable",
1630 log.Fields{
1631 "err": err,
1632 "deviceFlow": deviceFlow,
1633 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001634 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001635 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001636 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001637 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001638
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001639 }
Shrey Baid26912972020-04-16 21:02:31 +05301640 logger.Infow("flow-removed-from-device-successfully ",
1641 log.Fields{
1642 "flow": *deviceFlow,
1643 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001644 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301645}
1646
1647/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1648 //update core flows_proxy : flows_proxy.update('/', flows)
1649}
1650
1651func generateStoredId(flowId uint32, direction string)uint32{
1652
David K. Bainbridge82efc492019-09-04 09:57:11 -07001653 if direction == Upstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001654 logger.Debug("Upstream flow shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301655 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001656 }else if direction == Downstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001657 logger.Debug("Downstream flow not shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301658 return flowId
1659 }else{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001660 logger.Errorw("Unrecognized direction",log.Fields{"direction": direction})
manikkaraj kbf256be2019-03-25 00:13:48 +05301661 return flowId
1662 }
1663}
1664
1665*/
1666
David K. Bainbridge794735f2020-02-11 21:01:37 -08001667func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001668
1669 classifierInfo := make(map[string]interface{})
1670 actionInfo := make(map[string]interface{})
1671
1672 classifierInfo[EthType] = uint32(LldpEthType)
1673 classifierInfo[PacketTagType] = Untagged
1674 actionInfo[TrapToHost] = true
1675
1676 // LLDP flow is installed to trap LLDP packets on the NNI port.
1677 // We manage flow_id resource pool on per PON port basis.
1678 // Since this situation is tricky, as a hack, we pass the NNI port
1679 // index (network_intf_id) as PON port Index for the flow_id resource
1680 // pool. Also, there is no ONU Id available for trapping LLDP packets
1681 // on NNI port, use onu_id as -1 (invalid)
1682 // ****************** CAVEAT *******************
1683 // This logic works if the NNI Port Id falls within the same valid
1684 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1685 // we need to have a re-look at this.
1686 // *********************************************
1687
1688 var onuID = -1
1689 var uniID = -1
1690 var gemPortID = -1
1691
David K. Bainbridge794735f2020-02-11 21:01:37 -08001692 networkInterfaceID, err := IntfIDFromNniPortNum(portNo)
1693 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301694 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001695 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001696 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301697 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301698 logger.Infow("flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001699 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001700 }
npujarec5762e2020-01-01 14:08:48 +05301701 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001702
1703 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301704 return olterrors.NewErrNotFound("flow-id",
1705 log.Fields{
1706 "interface-id": networkInterfaceID,
1707 "onu-id": onuID,
1708 "uni-id": uniID,
1709 "gem-port-id": gemPortID,
1710 "cookie": flowStoreCookie,
1711 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001712 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001713 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001714 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1715 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301716 return olterrors.NewErrInvalidValue(
1717 log.Fields{
1718 "classifier": classifierInfo,
1719 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001720 }
Shrey Baid26912972020-04-16 21:02:31 +05301721 logger.Debugw("created-classifier-proto",
1722 log.Fields{
1723 "classifier": *classifierProto,
1724 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001725 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001726 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301727 return olterrors.NewErrInvalidValue(
1728 log.Fields{
1729 "action": actionInfo,
1730 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001731 }
Shrey Baid26912972020-04-16 21:02:31 +05301732 logger.Debugw("created-action-proto",
1733 log.Fields{
1734 "action": *actionProto,
1735 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001736
1737 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1738 OnuId: int32(onuID), // OnuId not required
1739 UniId: int32(uniID), // UniId not used
1740 FlowId: flowID,
1741 FlowType: Downstream,
1742 NetworkIntfId: int32(networkInterfaceID),
1743 GemportId: int32(gemPortID),
1744 Classifier: classifierProto,
1745 Action: actionProto,
1746 Priority: int32(flow.Priority),
1747 Cookie: flow.Cookie,
1748 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001749 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301750 return olterrors.NewErrFlowOp("add", flowID,
1751 log.Fields{
1752 "flow": downstreamflow,
1753 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001754 }
Shrey Baid26912972020-04-16 21:02:31 +05301755 logger.Infow("lldp-trap-on-nni-flow-added-to-device-successfully",
1756 log.Fields{
1757 "device-id": f.deviceHandler.device.Id,
1758 "onu-id": onuID,
1759 "flow-id": flowID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001760 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1761 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1762 int32(onuID),
1763 int32(uniID),
1764 flowID, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301765 return olterrors.NewErrPersistence("update", "flow", flowID,
1766 log.Fields{
1767 "flow": downstreamflow,
1768 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001769 }
1770 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301771}
1772
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001773func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1774 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001775}
1776
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001777//getOnuDevice to fetch onu from cache or core.
1778func (f *OpenOltFlowMgr) getOnuDevice(intfID uint32, onuID uint32) (*OnuDevice, error) {
1779 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1780 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1781 if !ok {
Shrey Baid26912972020-04-16 21:02:31 +05301782 logger.Debugw("couldnt-find-onu-in-cache",
1783 log.Fields{
1784 "intf-id": intfID,
1785 "onu-id": onuID,
1786 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001787 onuDevice, err := f.getChildDevice(intfID, onuID)
1788 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301789 return nil, olterrors.NewErrNotFound("onu-child-device",
1790 log.Fields{
1791 "onu-id": onuID,
1792 "intf-id": intfID,
1793 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001794 }
1795 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1796 //better to ad the device to cache here.
1797 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1798 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301799 logger.Debugw("found-onu-in-cache",
1800 log.Fields{
1801 "intf-id": intfID,
1802 "onu-id": onuID,
1803 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001804 }
1805
1806 return onuDev.(*OnuDevice), nil
1807}
1808
1809//getChildDevice to fetch onu
1810func (f *OpenOltFlowMgr) getChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
Shrey Baid26912972020-04-16 21:02:31 +05301811 logger.Infow("GetChildDevice",
1812 log.Fields{
1813 "pon-port": intfID,
1814 "onu-id": onuID,
1815 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001816 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001817 onuDevice, err := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
1818 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301819 return nil, olterrors.NewErrNotFound("onu",
1820 log.Fields{
1821 "interface-id": parentPortNo,
1822 "onu-id": onuID,
1823 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001824 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301825 }
Shrey Baid26912972020-04-16 21:02:31 +05301826 logger.Infow("successfully-received-child-device-from-core",
1827 log.Fields{
1828 "device-id": f.deviceHandler.device.Id,
1829 "child_device_id": onuDevice.Id,
1830 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301831 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301832}
1833
1834func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Shrey Baid26912972020-04-16 21:02:31 +05301835 logger.Info("unimplemented-flow %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301836 return nil
1837}
1838
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001839func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
Shrey Baid26912972020-04-16 21:02:31 +05301840 logger.Info("unimplemented-device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301841}
1842
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001843func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001844 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001845 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001846 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001847 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001848}
1849
Girish Gowdra6b130582019-11-20 16:45:20 +05301850func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001851 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301852 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301853 logger.Debugw("couldnt-find-onu-child-device",
1854 log.Fields{
1855 "intf-id": intfID,
1856 "onu-id": onuID,
1857 "uni-id": uniID,
1858 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001859 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301860 }
1861
1862 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Shrey Baid26912972020-04-16 21:02:31 +05301863 logger.Debugw("sending-gem-port-delete-to-openonu-adapter",
1864 log.Fields{
1865 "msg": *delGemPortMsg,
1866 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301867 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1868 delGemPortMsg,
1869 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301870 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001871 onuDev.deviceType,
1872 onuDev.deviceID,
1873 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301874 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1875 log.Fields{
1876 "from-adapter": f.deviceHandler.device.Type,
1877 "to-adapter": onuDev.deviceType,
1878 "onu-id": onuDev.deviceID,
1879 "proxyDeviceID": onuDev.proxyDeviceID,
1880 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301881 }
Shrey Baid26912972020-04-16 21:02:31 +05301882 logger.Infow("success-sending-del-gem-port-to-onu-adapter",
1883 log.Fields{
1884 "msg": delGemPortMsg,
1885 "from-adapter": f.deviceHandler.device.Type,
1886 "to-adapter": onuDev.deviceType,
1887 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301888 return nil
1889}
1890
1891func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001892 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301893 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301894 logger.Warnw("couldnt-find-onu-child-device",
1895 log.Fields{
1896 "intf-id": intfID,
1897 "onu-id": onuID,
1898 "uni-id": uniID,
1899 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001900 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301901 }
1902
1903 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Shrey Baid26912972020-04-16 21:02:31 +05301904 logger.Debugw("sending-tcont-delete-to-openonu-adapter",
1905 log.Fields{
1906 "msg": *delTcontMsg,
1907 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301908 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1909 delTcontMsg,
1910 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301911 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001912 onuDev.deviceType,
1913 onuDev.deviceID,
1914 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301915 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1916 log.Fields{
1917 "from-adapter": f.deviceHandler.device.Type,
1918 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1919 "proxyDeviceID": onuDev.proxyDeviceID,
1920 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301921 }
Shrey Baid26912972020-04-16 21:02:31 +05301922 logger.Infow("success-sending-del-tcont-to-onu-adapter",
1923 log.Fields{
1924 "msg": delTcontMsg,
1925 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301926 return nil
1927}
1928
Girish Gowdra3d633032019-12-10 16:37:05 +05301929func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1930 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1931 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1932 if val.(int) > 0 {
1933 pnFlDels := val.(int) - 1
1934 if pnFlDels > 0 {
Shrey Baid26912972020-04-16 21:02:31 +05301935 logger.Debugw("flow-delete-succeeded--more-pending",
1936 log.Fields{
1937 "intf": Intf,
1938 "onu-id": onuID,
1939 "uni-id": uniID,
1940 "currpendingflowcnt": pnFlDels,
1941 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301942 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1943 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301944 logger.Debugw("all-pending-flow-deletes-handled--removing-entry-from-map",
1945 log.Fields{
1946 "intf": Intf,
1947 "onu-id": onuID,
1948 "uni-id": uniID,
1949 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301950 f.pendingFlowDelete.Delete(pnFlDelKey)
1951 }
1952 }
1953 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301954 logger.Debugw("no-pending-delete-flows-found",
1955 log.Fields{
1956 "intf": Intf,
1957 "onu-id": onuID,
1958 "uni-id": uniID,
1959 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301960
1961 }
1962
1963}
1964
Girish Gowdrac3037402020-01-22 20:29:53 +05301965// Once the gemport is released for a given onu, it also has to be cleared from local cache
1966// which was used for deriving the gemport->logicalPortNo during packet-in.
1967// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1968// is conveyed to ONOS during packet-in OF message.
1969func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(intfID uint32, onuID uint32, gemPortID uint32) {
1970 f.lockCache.Lock()
1971 defer f.lockCache.Unlock()
Shrey Baid26912972020-04-16 21:02:31 +05301972 logger.Infow("deleting-gem-from-local-cache",
1973 log.Fields{
1974 "gem": gemPortID,
1975 "intf-id": intfID,
1976 "onu-id": onuID,
1977 "device-id": f.deviceHandler.device.Id,
1978 "onu-gem": f.onuGemInfo[intfID]})
Girish Gowdrac3037402020-01-22 20:29:53 +05301979 onugem := f.onuGemInfo[intfID]
serkant.uluderya96af4932020-02-20 16:58:48 -08001980 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301981 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001982 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301983 // If the gemport is found, delete it from local cache.
1984 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001985 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1986 onugem[i] = onu
Shrey Baid26912972020-04-16 21:02:31 +05301987 logger.Infow("removed-gemport-from-local-cache",
1988 log.Fields{
1989 "intf-id": intfID,
1990 "onu-id": onuID,
1991 "deletedgemport-id": gemPortID,
1992 "gemports": onu.GemPorts,
1993 "device-id": f.deviceHandler.device.Id})
Girish Gowdrac3037402020-01-22 20:29:53 +05301994 break
1995 }
1996 }
1997 break
1998 }
1999 }
2000}
2001
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302002//clearResources clears pon resources in kv store and the device
npujarec5762e2020-01-01 14:08:48 +05302003func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302004 gemPortID int32, flowID uint32, flowDirection string,
2005 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002006
Chaitrashree G S90a17952019-11-14 21:51:21 -05002007 tpID, err := getTpIDFromFlow(flow)
2008 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302009 return olterrors.NewErrNotFound("tp-id",
2010 log.Fields{
2011 "flow": flow,
2012 "intf": Intf,
2013 "onu-id": onuID,
2014 "uni-id": uniID,
2015 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002016 }
Gamze Abakafee36392019-10-03 11:17:24 +00002017
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002018 if len(updatedFlows) >= 0 {
2019 // There are still flows referencing the same flow_id.
2020 // So the flow should not be freed yet.
2021 // For ex: Case of HSIA where same flow is shared
2022 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00002023 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302024 olterrors.NewErrPersistence("update", "flow", flowID,
2025 log.Fields{
2026 "flow": updatedFlows,
2027 "device-id": f.deviceHandler.device.Id}, err).Log()
Girish Kumarf26e4882020-03-05 06:49:10 +00002028 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002029 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05302030 // Do this for subscriber flows only (not trap from NNI flows)
2031 if onuID != -1 && uniID != -1 {
2032 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
2033 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Shrey Baid26912972020-04-16 21:02:31 +05302034 logger.Debugw("creating-entry-for-pending-flow-delete",
2035 log.Fields{
2036 "flow-id": flowID,
2037 "intf": Intf,
2038 "onu-id": onuID,
2039 "uni-id": uniID,
2040 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302041 f.pendingFlowDelete.Store(pnFlDelKey, 1)
2042 } else {
2043 pnFlDels := val.(int) + 1
Shrey Baid26912972020-04-16 21:02:31 +05302044 logger.Debugw("updating-flow-delete-entry",
2045 log.Fields{
2046 "flow-id": flowID,
2047 "intf": Intf,
2048 "onu-id": onuID,
2049 "uni-id": uniID,
2050 "currPendingFlowCnt": pnFlDels,
2051 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302052 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
2053 }
2054
2055 defer f.deletePendingFlows(Intf, onuID, uniID)
2056 }
2057
Shrey Baid26912972020-04-16 21:02:31 +05302058 logger.Debugw("releasing-flow-id-to-resource-manager",
2059 log.Fields{
2060 "Intf": Intf,
2061 "onu-id": onuID,
2062 "uni-id": uniID,
2063 "flow-id": flowID,
2064 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302065 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002066
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002067 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302068 tpPath := f.getTPpath(Intf, uni, tpID)
Shrey Baid26912972020-04-16 21:02:31 +05302069 logger.Debugw("getting-techprofile-instance-for-subscriber",
2070 log.Fields{
2071 "TP-PATH": tpPath,
2072 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302073 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00002074 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +05302075 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
2076 log.Fields{
2077 "tp-id": tpID,
2078 "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002079 }
2080
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302081 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00002082 if f.isGemPortUsedByAnotherFlow(gemPK) {
2083 flowIDs := f.flowsUsedByGemPort[gemPK]
2084 for i, flowIDinMap := range flowIDs {
2085 if flowIDinMap == flowID {
2086 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302087 // everytime flowsUsedByGemPort cache is updated the same should be updated
2088 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002089 f.flowsUsedByGemPort[gemPK] = flowIDs
npujarec5762e2020-01-01 14:08:48 +05302090 f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00002091 break
2092 }
2093 }
Shrey Baid26912972020-04-16 21:02:31 +05302094 logger.Debugw("gem-port-id-is-still-used-by-other-flows",
2095 log.Fields{
2096 "gemport-id": gemPortID,
2097 "usedByFlows": flowIDs,
2098 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302099 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00002100 }
Shrey Baid26912972020-04-16 21:02:31 +05302101 logger.Debugf("gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05302102 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002103 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
2104 // 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 +05302105 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Girish Gowdrac3037402020-01-22 20:29:53 +05302106 f.deleteGemPortFromLocalCache(Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002107 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302108 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
2109 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002110 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05302111 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
2112 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002113 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05302114 // Delete the gem port on the ONU.
2115 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302116 logger.Errorw("error-processing-delete-gem-port-towards-onu",
2117 log.Fields{
2118 "err": err,
2119 "intf": Intf,
2120 "onu-id": onuID,
2121 "uni-id": uniID,
2122 "device-id": f.deviceHandler.device.Id,
2123 "gemport-id": gemPortID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302124 }
Gamze Abakafee36392019-10-03 11:17:24 +00002125
npujarec5762e2020-01-01 14:08:48 +05302126 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002127 if !ok {
npujarec5762e2020-01-01 14:08:48 +05302128 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
2129 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
2130 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
2131 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
2132 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302133 // Delete the TCONT on the ONU.
2134 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302135 logger.Errorw("error-processing-delete-tcont-towards-onu",
2136 log.Fields{
2137 "intf": Intf,
2138 "onu-id": onuID,
2139 "uni-id": uniID,
2140 "device-id": f.deviceHandler.device.Id,
2141 "alloc-id": techprofileInst.UsScheduler.AllocID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302142 }
Gamze Abakafee36392019-10-03 11:17:24 +00002143 }
2144 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002145 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302146 return nil
2147}
2148
David K. Bainbridge794735f2020-02-11 21:01:37 -08002149// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302150func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302151
Shrey Baid26912972020-04-16 21:02:31 +05302152 logger.Infow("clear-flow-from-resource-manager",
2153 log.Fields{
2154 "flowDirection": flowDirection,
2155 "flow": *flow,
2156 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002157
2158 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05302159 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002160 return
2161 }
2162
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302163 var updatedFlows []rsrcMgr.FlowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302164 classifierInfo := make(map[string]interface{})
2165
2166 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
2167 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002168 logger.Error(err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302169 return
2170 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302171
David K. Bainbridge794735f2020-02-11 21:01:37 -08002172 onuID := int32(onu)
2173 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302174
2175 for _, field := range flows.GetOfbFields(flow) {
2176 if field.Type == flows.IP_PROTO {
2177 classifierInfo[IPProto] = field.GetIpProto()
Shrey Baid26912972020-04-16 21:02:31 +05302178 logger.Debugw("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302179 }
2180 }
Shrey Baid26912972020-04-16 21:02:31 +05302181 logger.Infow("extracted-access-info-from-flow-to-be-deleted",
2182 log.Fields{
2183 "ponIntf": Intf,
2184 "onu-id": onuID,
2185 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302186
2187 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2188 onuID = -1
2189 uniID = -1
Shrey Baid26912972020-04-16 21:02:31 +05302190 logger.Debug("trap-on-nni-flow-set-oni--uni-to- -1")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002191 Intf, err = IntfIDFromNniPortNum(inPort)
2192 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002193 logger.Errorw("invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002194 log.Fields{
2195 "port-number": inPort,
2196 "error": err})
2197 return
2198 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302199 }
npujarec5762e2020-01-01 14:08:48 +05302200 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002201 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302202 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302203 if flowInfo == nil {
Shrey Baid26912972020-04-16 21:02:31 +05302204 logger.Debugw("no-flowinfo-found-in-kv-store",
2205 log.Fields{
2206 "intf": Intf,
2207 "onu-id": onuID,
2208 "uni-id": uniID,
2209 "flow-id": flowID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302210 return
2211 }
2212 updatedFlows = nil
2213 for _, flow := range *flowInfo {
2214 updatedFlows = append(updatedFlows, flow)
2215 }
2216
2217 for i, storedFlow := range updatedFlows {
2218 if flow.Id == storedFlow.LogicalFlowID {
2219 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Shrey Baid26912972020-04-16 21:02:31 +05302220 logger.Debugw("flow-to-be-deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002221 // DKB
2222 if err = f.removeFlowFromDevice(&removeFlowMessage); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002223 logger.Errorw("failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002224 return
2225 }
Shrey Baid26912972020-04-16 21:02:31 +05302226 logger.Info("flow-removed-from-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002227 //Remove the Flow from FlowInfo
2228 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
2229 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
2230 flowID, flowDirection, portNum, updatedFlows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302231 logger.Error("failed-to-clear-resources-for-flow",
2232 log.Fields{
2233 "flow": storedFlow,
2234 "device-id": f.deviceHandler.device.Id,
2235 "flow-id": flowID,
2236 "onu-id": onuID,
2237 "intf": Intf})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302238 return
2239 }
2240 }
2241 }
2242 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002243}
2244
Esin Karamanccb714b2019-11-29 15:02:06 +00002245//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
2246// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05302247func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002248 classifierInfo := make(map[string]interface{})
2249 formulateClassifierInfoFromFlow(classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00002250 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002251
2252 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302253 logger.Warnw("no-inport-found--cannot-release-resources-of-the-multicast-flow", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002254 return
2255 }
2256
Esin Karamanccb714b2019-11-29 15:02:06 +00002257 var onuID = int32(NoneOnuID)
2258 var uniID = int32(NoneUniID)
2259 var flowID uint32
2260 var updatedFlows []rsrcMgr.FlowInfo
2261
npujarec5762e2020-01-01 14:08:48 +05302262 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002263
2264 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302265 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002266 if flowInfo == nil {
Shrey Baid26912972020-04-16 21:02:31 +05302267 logger.Debugw("no-multicast-flowinfo-found-in-the-kv-store",
2268 log.Fields{
2269 "intf": networkInterfaceID,
2270 "onu-id": onuID,
2271 "uni-id": uniID,
2272 "flow-id": flowID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002273 continue
2274 }
2275 updatedFlows = nil
2276 for _, flow := range *flowInfo {
2277 updatedFlows = append(updatedFlows, flow)
2278 }
2279 for i, storedFlow := range updatedFlows {
2280 if flow.Id == storedFlow.LogicalFlowID {
2281 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Shrey Baid26912972020-04-16 21:02:31 +05302282 logger.Debugw("multicast-flow-to-be-deleted",
2283 log.Fields{
2284 "flow": storedFlow,
2285 "flow-id": flow.Id,
2286 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002287 //remove from device
David K. Bainbridge794735f2020-02-11 21:01:37 -08002288 if err := f.removeFlowFromDevice(&removeFlowMessage); err != nil {
2289 // DKB
Girish Kumar2ad402b2020-03-20 19:45:12 +00002290 logger.Errorw("failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002291 log.Fields{
2292 "flow-id": flow.Id,
2293 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002294 return
2295 }
Shrey Baid26912972020-04-16 21:02:31 +05302296 logger.Infow("multicast-flow-removed-from-device-successfully", log.Fields{"flow-id": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002297 //Remove the Flow from FlowInfo
2298 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05302299 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302300 logger.Errorw("failed-to-delete-multicast-flow-from-the-kv-store",
2301 log.Fields{"flow": storedFlow,
2302 "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002303 return
2304 }
2305 //release flow id
Shrey Baid26912972020-04-16 21:02:31 +05302306 logger.Debugw("releasing-multicast-flow-id",
2307 log.Fields{"flow-id": flowID,
2308 "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05302309 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002310 }
2311 }
2312 }
2313}
2314
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002315//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002316func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Shrey Baid26912972020-04-16 21:02:31 +05302317 logger.Infow("removing-flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302318 var direction string
2319 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002320
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302321 for _, action := range flows.GetActions(flow) {
2322 if action.Type == flows.OUTPUT {
2323 if out := action.GetOutput(); out != nil {
2324 actionInfo[Output] = out.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002325 logger.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302326 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302327 logger.Error("invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002328 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002329 }
2330 }
2331 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002332
2333 if flows.HasGroup(flow) {
2334 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07002335 f.clearFlowFromResourceManager(ctx, flow, direction)
2336 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002337 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302338 direction = Upstream
2339 } else {
2340 direction = Downstream
2341 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302342
Girish Gowdracefae192020-03-19 18:14:10 -07002343 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(flow, direction)
2344 if err != nil {
2345 return err
2346 }
2347
2348 userKey := tpLockKey{intfID, onuID, uniID}
2349
2350 // Serialize flow removes on a per subscriber basis
2351 if f.perUserFlowHandleLock.TryLock(userKey) {
2352 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
2353 f.perUserFlowHandleLock.Unlock(userKey)
2354 } else {
2355 // Ideally this should never happen
Shrey Baid26912972020-04-16 21:02:31 +05302356 logger.Errorw("failed-to-acquire-lock-to-remove-flow--remove-aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07002357 return errors.New("failed-to-acquire-per-user-lock")
2358 }
2359
2360 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002361}
2362
Girish Gowdra3d633032019-12-10 16:37:05 +05302363func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
2364 uniID uint32, ch chan bool) {
2365 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2366 for {
2367 select {
2368 case <-time.After(20 * time.Millisecond):
2369 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Shrey Baid26912972020-04-16 21:02:31 +05302370 logger.Debug("pending-flow-deletes-completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05302371 ch <- true
2372 return
2373 }
2374 case <-ctx.Done():
Shrey Baid26912972020-04-16 21:02:31 +05302375 logger.Error("flow-delete-wait-handler-routine-canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05302376 return
2377 }
2378 }
2379}
2380
Esin Karamanae41e2b2019-12-17 18:13:13 +00002381//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2382func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2383 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2384 if ethType, ok := classifierInfo[EthType]; ok {
2385 if ethType.(uint32) == IPv4EthType {
2386 if ipProto, ok := classifierInfo[IPProto]; ok {
2387 if ipProto.(uint32) == IgmpProto {
2388 return true
2389 }
2390 }
2391 }
2392 }
2393 }
2394 return false
2395}
2396
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002397// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302398// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002399func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002400 classifierInfo := make(map[string]interface{})
2401 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002402 var UsMeterID uint32
2403 var DsMeterID uint32
2404
Shrey Baid26912972020-04-16 21:02:31 +05302405 logger.Infow("adding-flow",
2406 log.Fields{
2407 "flow": flow,
2408 "flowmetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002409 formulateClassifierInfoFromFlow(classifierInfo, flow)
2410
2411 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
2412 if err != nil {
2413 // Error logging is already done in the called function
2414 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002415 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302416 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002417
Esin Karamanccb714b2019-11-29 15:02:06 +00002418 if flows.HasGroup(flow) {
2419 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002420 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002421 }
2422
manikkaraj k17652a72019-05-06 09:06:36 -04002423 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00002424 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
2425 if err != nil {
2426 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002427 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002428 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002429
Shrey Baid26912972020-04-16 21:02:31 +05302430 logger.Debugw("flow-ports",
2431 log.Fields{
2432 "classifierinfo_inport": classifierInfo[InPort],
2433 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002434 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002435
Humera Kouser94d7a842019-08-25 19:04:32 -04002436 if ethType, ok := classifierInfo[EthType]; ok {
2437 if ethType.(uint32) == LldpEthType {
Shrey Baid26912972020-04-16 21:02:31 +05302438 logger.Info("adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002439 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002440 }
2441 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002442 if ipProto, ok := classifierInfo[IPProto]; ok {
2443 if ipProto.(uint32) == IPProtoDhcp {
2444 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302445 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002446 logger.Debug("trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002447 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002448 }
2449 }
2450 }
2451 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002452 if isIgmpTrapDownstreamFlow(classifierInfo) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002453 logger.Debug("trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002454 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002455 }
A R Karthick1f85b802019-10-11 05:06:05 +00002456
2457 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
npujarec5762e2020-01-01 14:08:48 +05302458 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002459
Chaitrashree G S90a17952019-11-14 21:51:21 -05002460 TpID, err := getTpIDFromFlow(flow)
2461 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302462 return olterrors.NewErrNotFound("tpid-for-flow",
2463 log.Fields{
2464 "flow": flow,
2465 "intf-id": IntfID,
2466 "onu-id": onuID,
2467 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002468 }
Shrey Baid26912972020-04-16 21:02:31 +05302469 logger.Debugw("tpid-for-this-subcriber",
2470 log.Fields{
2471 "tp-id": TpID,
2472 "intf-id": intfID,
2473 "onu-id": onuID,
2474 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002475 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002476 UsMeterID = flows.GetMeterIdFromFlow(flow)
Shrey Baid26912972020-04-16 21:02:31 +05302477 logger.Debugw("upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002478 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002479 DsMeterID = flows.GetMeterIdFromFlow(flow)
Shrey Baid26912972020-04-16 21:02:31 +05302480 logger.Debugw("downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002481
2482 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302483
2484 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2485 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Shrey Baid26912972020-04-16 21:02:31 +05302486 logger.Debugw("no-pending-flows-found--going-ahead-with-flow-install",
2487 log.Fields{
2488 "intf-id": intfID,
2489 "onu-id": onuID,
2490 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302491 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302492 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05302493 pendingFlowDelComplete := make(chan bool)
2494 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
2495 select {
2496 case <-pendingFlowDelComplete:
Shrey Baid26912972020-04-16 21:02:31 +05302497 logger.Debugw("all-pending-flow-deletes-completed",
2498 log.Fields{
2499 "intf-id": intfID,
2500 "onu-id": onuID,
2501 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302502 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302503
2504 case <-time.After(10 * time.Second):
Shrey Baid26912972020-04-16 21:02:31 +05302505 return olterrors.NewErrTimeout("pending-flow-deletes",
2506 log.Fields{
2507 "intf-id": intfID,
2508 "onu-id": onuID,
2509 "uni-id": uniID}, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +05302510 }
2511 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002512 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002513}
2514
Esin Karamanccb714b2019-11-29 15:02:06 +00002515// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002516func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002517 classifierInfo[PacketTagType] = DoubleTag
Shrey Baid26912972020-04-16 21:02:31 +05302518 logger.Debugw("add-multicast-flow", log.Fields{
2519 "classifier-info": classifierInfo,
2520 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002521
Esin Karaman65409d82020-03-18 10:58:18 +00002522 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002523 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002524 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002525 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002526 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
2527 //otherwise, classification is based on ipv4_dst by default.
2528 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
2529 mcastFlowClassificationByEthDst := false
2530
2531 if mcastFlowClassificationByEthDst {
2532 //replace ipDst with ethDst
2533 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
2534 flows.IsMulticastIp(ipv4Dst.(uint32)) {
2535 // replace ipv4_dst classifier with eth_dst
2536 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
2537 delete(classifierInfo, Ipv4Dst)
2538 classifierInfo[EthDst] = multicastMac
Shrey Baid26912972020-04-16 21:02:31 +05302539 logger.Debugw("multicast-ip-to-mac-conversion-success",
2540 log.Fields{
2541 "ip:": ipv4Dst.(uint32),
2542 "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002543 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002544 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002545 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002546
David K. Bainbridge794735f2020-02-11 21:01:37 -08002547 onuID := NoneOnuID
2548 uniID := NoneUniID
2549 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00002550
David K. Bainbridge794735f2020-02-11 21:01:37 -08002551 flowStoreCookie := getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302552 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05302553 logger.Infow("multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002554 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002555 }
npujarec5762e2020-01-01 14:08:48 +05302556 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00002557 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302558 return olterrors.NewErrNotFound("multicast-flow-id",
2559 log.Fields{
2560 "interface-id": networkInterfaceID,
2561 "onu-id": onuID,
2562 "uni-id": uniID,
2563 "gem-port-id": gemPortID,
2564 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002565 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002566 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002567 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2568 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002569 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002570 }
2571 groupID := actionInfo[GroupID].(uint32)
2572 multicastFlow := openoltpb2.Flow{
2573 FlowId: flowID,
2574 FlowType: Multicast,
2575 NetworkIntfId: int32(networkInterfaceID),
2576 GroupId: groupID,
2577 Classifier: classifierProto,
2578 Priority: int32(flow.Priority),
2579 Cookie: flow.Cookie}
2580
David K. Bainbridge794735f2020-02-11 21:01:37 -08002581 if err = f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002582 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002583 }
Shrey Baid26912972020-04-16 21:02:31 +05302584 logger.Info("multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002585 //get cached group
2586 group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true)
2587 if err == nil {
2588 //calling groupAdd to set group members after multicast flow creation
Andrea Campanellac63bba92020-03-10 17:01:04 +01002589 if err = f.ModifyGroup(ctx, group); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002590 //cached group can be removed now
2591 f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002592 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002593 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002594 }
2595 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002596
2597 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2598 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2599 int32(onuID),
2600 int32(uniID),
2601 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002602 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002603 }
2604 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002605}
2606
Esin Karaman65409d82020-03-18 10:58:18 +00002607//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2608func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2609 if inPort, ok := classifierInfo[InPort]; ok {
2610 nniInterfaceID, err := IntfIDFromNniPortNum(inPort.(uint32))
2611 if err != nil {
2612 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2613 }
2614 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002615 }
Esin Karaman65409d82020-03-18 10:58:18 +00002616 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302617 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002618 if e == nil && len(nniPorts) > 0 {
2619 return nniPorts[0], nil
2620 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302621 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002622}
2623
2624// AddGroup add or update the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002625func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002626 logger.Infow("add-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002627 if group == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002628 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002629 }
2630
2631 groupToOlt := openoltpb2.Group{
2632 GroupId: group.Desc.GroupId,
2633 Command: openoltpb2.Group_SET_MEMBERS,
2634 Action: f.buildGroupAction(),
2635 }
2636
Shrey Baid26912972020-04-16 21:02:31 +05302637 logger.Debugw("sending-group-to-device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05302638 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002639 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002640 return olterrors.NewErrAdapter("add-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002641 }
2642 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05302643 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002644 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002645 }
Shrey Baid26912972020-04-16 21:02:31 +05302646 logger.Infow("add-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002647 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002648}
2649
2650//buildGroupAction creates and returns a group action
2651func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2652 var actionCmd openoltpb2.ActionCmd
2653 var action openoltpb2.Action
2654 action.Cmd = &actionCmd
2655 //pop outer vlan
2656 action.Cmd.RemoveOuterTag = true
2657 return &action
2658}
2659
2660// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002661func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002662 logger.Infow("modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002663 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002664 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002665 }
2666
Andrea Campanellac63bba92020-03-10 17:01:04 +01002667 newGroup := f.buildGroup(group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002668 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302669 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002670
2671 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002672 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002673 }
2674
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002675 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002676 if groupExists {
2677 // group already exists
2678 current = f.buildGroup(group.Desc.GroupId, val.Desc.GetBuckets())
Shrey Baid26912972020-04-16 21:02:31 +05302679 logger.Debugw("modify-group--group exists",
2680 log.Fields{
2681 "group on the device": val,
2682 "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002683 } else {
2684 current = f.buildGroup(group.Desc.GroupId, nil)
2685 }
2686
Shrey Baid26912972020-04-16 21:02:31 +05302687 logger.Debugw("modify-group--comparing-current-and-new",
2688 log.Fields{
2689 "group on the device": current,
2690 "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002691 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002692 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002693 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002694 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002695
Shrey Baid26912972020-04-16 21:02:31 +05302696 logger.Infow("modify-group--differences found", log.Fields{
2697 "membersToBeAdded": membersToBeAdded,
2698 "membersToBeRemoved": membersToBeRemoved,
2699 "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002700
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002701 groupToOlt := openoltpb2.Group{
2702 GroupId: group.Desc.GroupId,
2703 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002704 var errAdd, errRemoved error
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002705 if membersToBeAdded != nil && len(membersToBeAdded) > 0 {
2706 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2707 groupToOlt.Members = membersToBeAdded
2708 //execute addMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002709 errAdd = f.callGroupAddRemove(&groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002710 }
2711 if membersToBeRemoved != nil && len(membersToBeRemoved) > 0 {
2712 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2713 groupToOlt.Members = membersToBeRemoved
2714 //execute removeMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002715 errRemoved = f.callGroupAddRemove(&groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002716 }
2717
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002718 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002719 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302720 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002721 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002722 }
Shrey Baid26912972020-04-16 21:02:31 +05302723 logger.Infow("modify-group-was-success--storing-group",
2724 log.Fields{
2725 "group": group,
2726 "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002727 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302728 logger.Warnw("one-of-the-group-add/remove-operations-failed--cannot-save-group-modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002729 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002730 if errAdd != nil {
2731 return errAdd
2732 }
2733 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002734 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002735 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002736}
2737
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002738//callGroupAddRemove performs add/remove buckets operation for the indicated group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002739func (f *OpenOltFlowMgr) callGroupAddRemove(group *openoltpb2.Group) error {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002740 if err := f.performGroupOperation(group); err != nil {
2741 st, _ := status.FromError(err)
2742 //ignore already exists error code
2743 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002744 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002745 }
2746 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002747 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002748}
2749
2750//findDiff compares group members and finds members which only exists in groups2
2751func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2752 var members []*openoltpb2.GroupMember
2753 for _, bucket := range group2.Members {
2754 if !f.contains(group1.Members, bucket) {
2755 // bucket does not exist and must be added
2756 members = append(members, bucket)
2757 }
2758 }
2759 return members
2760}
2761
2762//contains returns true if the members list contains the given member; false otherwise
2763func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2764 for _, groupMember := range members {
2765 if groupMember.InterfaceId == member.InterfaceId {
2766 return true
2767 }
2768 }
2769 return false
2770}
2771
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002772//performGroupOperation call performGroupOperation operation of openolt proto
2773func (f *OpenOltFlowMgr) performGroupOperation(group *openoltpb2.Group) error {
Shrey Baid26912972020-04-16 21:02:31 +05302774 logger.Debugw("sending-group-to-device",
2775 log.Fields{
2776 "groupToOlt": group,
2777 "command": group.Command})
Esin Karamanccb714b2019-11-29 15:02:06 +00002778 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2779 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002780 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002781 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002782 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002783}
2784
2785//buildGroup build openoltpb2.Group from given group id and bucket list
2786func (f *OpenOltFlowMgr) buildGroup(groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
2787 group := openoltpb2.Group{
2788 GroupId: groupID}
2789 // create members of the group
2790 if buckets != nil {
2791 for _, ofBucket := range buckets {
2792 member := f.buildMember(ofBucket)
2793 if member != nil && !f.contains(group.Members, member) {
2794 group.Members = append(group.Members, member)
2795 }
2796 }
2797 }
2798 return &group
2799}
2800
2801//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
2802func (f *OpenOltFlowMgr) buildMember(ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
2803 var outPort uint32
2804 outPortFound := false
2805 for _, ofAction := range ofBucket.Actions {
2806 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2807 outPort = ofAction.GetOutput().Port
2808 outPortFound = true
2809 }
2810 }
2811
2812 if !outPortFound {
Shrey Baid26912972020-04-16 21:02:31 +05302813 logger.Debugw("bucket-skipped-since-no-out-port-found-in-it", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002814 return nil
2815 }
2816 interfaceID := IntfIDFromUniPortNum(outPort)
Shrey Baid26912972020-04-16 21:02:31 +05302817 logger.Debugw("got-associated-interface-id-of-the-port",
2818 log.Fields{
2819 "portNumber:": outPort,
2820 "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002821 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2822 member := openoltpb2.GroupMember{
2823 InterfaceId: interfaceID,
2824 InterfaceType: openoltpb2.GroupMember_PON,
2825 GemPortId: groupInfo.gemPortID,
2826 Priority: groupInfo.servicePriority,
2827 }
2828 //add member to the group
2829 return &member
2830 }
Shrey Baid26912972020-04-16 21:02:31 +05302831 logger.Warnf("bucket-skipped-since-interface-2-gem-mapping-cannot-be-found", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002832 return nil
2833}
2834
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002835//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04002836func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002837
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002838 onuDev, err := f.getOnuDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302839 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302840 logger.Errorw("couldnt-find-onu-child-device",
2841 log.Fields{
2842 "intf-id": intfID,
2843 "onu-id": onuID,
2844 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002845 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302846 }
Shrey Baid26912972020-04-16 21:02:31 +05302847 logger.Debugw("got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002848
Manikkaraj kb1d51442019-07-23 10:41:02 -04002849 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002850 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Shrey Baid26912972020-04-16 21:02:31 +05302851 logger.Debugw("sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
manikkaraj k17652a72019-05-06 09:06:36 -04002852 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2853 tpDownloadMsg,
2854 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302855 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002856 onuDev.deviceType,
2857 onuDev.deviceID,
2858 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002859 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302860 return olterrors.NewErrCommunication("send-techprofile-download-request",
2861 log.Fields{
2862 "from-adapter": f.deviceHandler.device.Type,
2863 "to-adapter": onuDev.deviceType,
2864 "onu-id": onuDev.deviceID,
2865 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002866 }
Shrey Baid26912972020-04-16 21:02:31 +05302867 logger.Infow("success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302868 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302869}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002870
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302871//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002872func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302873
2874 f.lockCache.Lock()
2875 defer f.lockCache.Unlock()
2876 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2877 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002878 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002879 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302880 }
Shrey Baid26912972020-04-16 21:02:31 +05302881 logger.Infow("updated-onuinfo",
2882 log.Fields{
2883 "intf-id": intfID,
2884 "onu-id": onuID,
2885 "serial-num": serialNum,
2886 "onu": onu,
2887 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002888 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002889}
2890
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302891//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302892func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302893 f.lockCache.Lock()
2894 defer f.lockCache.Unlock()
Shrey Baid26912972020-04-16 21:02:31 +05302895 logger.Infow("adding-gem-to-onu-info-map",
2896 log.Fields{
2897 "gem": gemPort,
2898 "intf": intfID,
2899 "onu": onuID,
2900 "device-id": f.deviceHandler.device.Id,
2901 "onu-gem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302902 onugem := f.onuGemInfo[intfID]
2903 // update the gem to the local cache as well as to kv strore
2904 for idx, onu := range onugem {
2905 if onu.OnuID == onuID {
2906 // check if gem already exists , else update the cache and kvstore
2907 for _, gem := range onu.GemPorts {
2908 if gem == gemPort {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002909 logger.Debugw("gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302910 log.Fields{
2911 "gem": gemPort,
2912 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302913 return
2914 }
2915 }
2916 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2917 f.onuGemInfo[intfID] = onugem
2918 }
2919 }
npujarec5762e2020-01-01 14:08:48 +05302920 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302921 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302922 logger.Errorw("failed-to-add-gem-to-onu",
2923 log.Fields{
2924 "intf-id": intfID,
2925 "onu-id": onuID,
2926 "gemPort": gemPort,
2927 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002928 return
2929 }
Shrey Baid26912972020-04-16 21:02:31 +05302930 logger.Infow("gem-added-to-onu-info-map",
2931 log.Fields{
2932 "gem": gemPort,
2933 "intf": intfID,
2934 "onu": onuID,
2935 "device-id": f.deviceHandler.device.Id,
2936 "onu-gem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002937}
2938
2939// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002940
2941//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
2942func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302943
2944 f.lockCache.Lock()
2945 defer f.lockCache.Unlock()
2946
Shrey Baid26912972020-04-16 21:02:31 +05302947 logger.Infow("getting-onu-id-from-gem-port-and-pon-port",
2948 log.Fields{
2949 "device-id": f.deviceHandler.device.Id,
2950 "onu-geminfo": f.onuGemInfo[intfID],
2951 "serial-number": serialNumber,
2952 "intf-id": intfID,
2953 "gemport-id": gemPortID})
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002954
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302955 // get onuid from the onugem info cache
2956 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002957
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302958 for _, onu := range onugem {
2959 for _, gem := range onu.GemPorts {
2960 if gem == gemPortID {
2961 return onu.OnuID, nil
2962 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002963 }
2964 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302965 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002966 "serial-number": serialNumber,
2967 "interface-id": intfID,
2968 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00002969 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002970}
2971
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002972//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302973func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002974 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002975 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002976 var err error
2977
2978 if packetIn.IntfType == "pon" {
2979 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002980 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002981 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002982 return logicalPortNum, err
2983 }
2984 if packetIn.PortNo != 0 {
2985 logicalPortNum = packetIn.PortNo
2986 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002987 uniID := uint32(0) // FIXME - multi-uni support
2988 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002989 }
2990 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
npujarec5762e2020-01-01 14:08:48 +05302991 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002992 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002993 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002994 }
Shrey Baid26912972020-04-16 21:02:31 +05302995 logger.Infow("retrieved-logicalport-from-packet-in",
2996 log.Fields{
2997 "logical-port-num": logicalPortNum,
2998 "intf-type": packetIn.IntfType,
2999 "packet": hex.EncodeToString(packetIn.Pkt),
3000 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003001 return logicalPortNum, nil
3002}
3003
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003004//GetPacketOutGemPortID returns gemPortId
npujarec5762e2020-01-01 14:08:48 +05303005func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003006 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003007 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303008
3009 f.lockCache.Lock()
3010 defer f.lockCache.Unlock()
3011 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
3012
3013 gemPortID, ok := f.packetInGemPort[pktInkey]
3014 if ok {
Shrey Baid26912972020-04-16 21:02:31 +05303015 logger.Debugw("found-gemport-for-pktin-key",
3016 log.Fields{
3017 "pktinkey": pktInkey,
3018 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303019 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003020 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303021 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
npujarec5762e2020-01-01 14:08:48 +05303022 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303023 if err == nil {
3024 if gemPortID != 0 {
3025 f.packetInGemPort[pktInkey] = gemPortID
Shrey Baid26912972020-04-16 21:02:31 +05303026 logger.Infow("found-gem-port-from-kv-store-and-updating-cache-with-gemport",
3027 log.Fields{
3028 "pktinkey": pktInkey,
3029 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303030 return gemPortID, nil
3031 }
3032 }
Shrey Baid26912972020-04-16 21:02:31 +05303033 return uint32(0), olterrors.NewErrNotFound("gem-port",
3034 log.Fields{
3035 "pktinkey": pktInkey,
3036 "gem": gemPortID}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003037}
3038
npujarec5762e2020-01-01 14:08:48 +05303039func installFlowOnAllGemports(ctx context.Context,
3040 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003041 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003042 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05303043 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303044 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303045 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003046 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003047 args map[string]uint32,
3048 classifier map[string]interface{}, action map[string]interface{},
3049 logicalFlow *ofp.OfpFlowStats,
3050 gemPorts []uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303051 TpInst *tp.TechProfile,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003052 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00003053 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003054 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003055 vlanID ...uint32) {
Shrey Baid26912972020-04-16 21:02:31 +05303056 logger.Debugw("installing-flow-on-all-gem-ports",
3057 log.Fields{
3058 "FlowType": FlowType,
3059 "gemPorts": gemPorts,
3060 "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05303061
Gamze Abaka724d0852020-03-18 12:10:24 +00003062 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
3063 // We need to trim prefix "0b", before further processing
3064 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
3065 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
3066
3067 // If a particular character in the string is set to '1', identify the index of this character from
3068 // the LSB position which marks the PCP bit consumed by the given gem port.
3069 // This PCP bit now becomes a classifier in the flow.
3070
3071 attributes := TpInst.DownstreamGemPortAttributeList
3072 if direction == Upstream {
3073 attributes = TpInst.UpstreamGemPortAttributeList
3074 }
3075
3076 for _, gemPortAttribute := range attributes {
3077 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
3078 continue
3079 }
3080 gemPortID := gemPortAttribute.GemportID
3081 if allPbitsMarked(gemPortAttribute.PbitMap) {
3082 classifier[VlanPcp] = uint32(VlanPCPMask)
3083 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003084 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003085 } else if FlowType == EapolFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003086 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003087 }
3088 } else {
3089 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
3090 if pbitSet == BinaryBit1 {
3091 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3092 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003093 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003094 } else if FlowType == EapolFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003095 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003096 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05303097 }
3098 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04003099 }
3100 }
3101}
3102
Gamze Abaka724d0852020-03-18 12:10:24 +00003103func allPbitsMarked(pbitMap string) bool {
3104 for pos, pBit := range pbitMap {
3105 if pos >= 2 && pBit != BinaryBit1 {
3106 return false
3107 }
3108 }
3109 return true
3110}
3111
David K. Bainbridge794735f2020-02-11 21:01:37 -08003112func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05303113 logger.Debug("adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003114 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003115 classifier[PacketTagType] = DoubleTag
3116 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003117 /* We manage flowId resource pool on per PON port basis.
3118 Since this situation is tricky, as a hack, we pass the NNI port
3119 index (network_intf_id) as PON port Index for the flowId resource
3120 pool. Also, there is no ONU Id available for trapping DHCP packets
3121 on NNI port, use onu_id as -1 (invalid)
3122 ****************** CAVEAT *******************
3123 This logic works if the NNI Port Id falls within the same valid
3124 range of PON Port Ids. If this doesn't work for some OLT Vendor
3125 we need to have a re-look at this.
3126 *********************************************
3127 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003128 onuID := -1
3129 uniID := -1
3130 gemPortID := -1
3131 allocID := -1
David K. Bainbridge794735f2020-02-11 21:01:37 -08003132 networkInterfaceID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303133 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303134 return olterrors.NewErrNotFound("nni-intreface-id",
3135 log.Fields{
3136 "classifier": classifier,
3137 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003138 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303139 }
3140
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003141 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303142 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05303143 logger.Info("flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003144 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003145 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003146 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003147 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303148 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id",
3149 log.Fields{
3150 "interface-id": networkInterfaceID,
3151 "onu-id": onuID,
3152 "uni-id": uniID,
3153 "gem-port-id": gemPortID,
3154 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003155 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003156 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003157 classifierProto, err := makeOpenOltClassifierField(classifier)
3158 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003159 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003160 }
Shrey Baid26912972020-04-16 21:02:31 +05303161 logger.Debugw("created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003162 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003163 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003164 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003165 }
Shrey Baid26912972020-04-16 21:02:31 +05303166 logger.Debugw("created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003167 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3168 OnuId: int32(onuID), // OnuId not required
3169 UniId: int32(uniID), // UniId not used
3170 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07003171 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003172 AllocId: int32(allocID), // AllocId not used
3173 NetworkIntfId: int32(networkInterfaceID),
3174 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003175 Classifier: classifierProto,
3176 Action: actionProto,
3177 Priority: int32(logicalFlow.Priority),
3178 Cookie: logicalFlow.Cookie,
3179 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003180 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003181 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003182 }
Shrey Baid26912972020-04-16 21:02:31 +05303183 logger.Info("dhcp-trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003184 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3185 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3186 int32(onuID),
3187 int32(uniID),
3188 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003189 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003190 }
3191 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003192}
salmansiddiqui7ac62132019-08-22 03:58:50 +00003193
Esin Karamanae41e2b2019-12-17 18:13:13 +00003194//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
3195func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
3196 var packetType string
3197 ovid, ivid := false, false
3198 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
3199 vid := vlanID & VlanvIDMask
3200 if vid != ReservedVlan {
3201 ovid = true
3202 }
3203 }
3204 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
3205 vid := uint32(metadata)
3206 if vid != ReservedVlan {
3207 ivid = true
3208 }
3209 }
3210 if ovid && ivid {
3211 packetType = DoubleTag
3212 } else if !ovid && !ivid {
3213 packetType = Untagged
3214 } else {
3215 packetType = SingleTag
3216 }
3217 return packetType
3218}
3219
3220//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08003221func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05303222 logger.Infow("adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003223 action := make(map[string]interface{})
3224 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
3225 action[TrapToHost] = true
3226 /* We manage flowId resource pool on per PON port basis.
3227 Since this situation is tricky, as a hack, we pass the NNI port
3228 index (network_intf_id) as PON port Index for the flowId resource
3229 pool. Also, there is no ONU Id available for trapping packets
3230 on NNI port, use onu_id as -1 (invalid)
3231 ****************** CAVEAT *******************
3232 This logic works if the NNI Port Id falls within the same valid
3233 range of PON Port Ids. If this doesn't work for some OLT Vendor
3234 we need to have a re-look at this.
3235 *********************************************
3236 */
3237 onuID := -1
3238 uniID := -1
3239 gemPortID := -1
3240 allocID := -1
3241 networkInterfaceID, err := getNniIntfID(classifier, action)
3242 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303243 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003244 "classifier": classifier,
3245 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003246 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003247 }
3248 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303249 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05303250 logger.Info("igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003251 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003252 }
npujarec5762e2020-01-01 14:08:48 +05303253 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003254 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303255 return olterrors.NewErrNotFound("igmp-flow-id",
3256 log.Fields{
3257 "interface-id": networkInterfaceID,
3258 "onu-id": onuID,
3259 "uni-id": uniID,
3260 "gem-port-id": gemPortID,
3261 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003262 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003263 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003264 classifierProto, err := makeOpenOltClassifierField(classifier)
3265 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003266 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003267 }
Shrey Baid26912972020-04-16 21:02:31 +05303268 logger.Debugw("created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003269 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003270 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003271 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003272 }
Shrey Baid26912972020-04-16 21:02:31 +05303273 logger.Debugw("created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003274 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3275 OnuId: int32(onuID), // OnuId not required
3276 UniId: int32(uniID), // UniId not used
3277 FlowId: flowID,
3278 FlowType: Downstream,
3279 AllocId: int32(allocID), // AllocId not used
3280 NetworkIntfId: int32(networkInterfaceID),
3281 GemportId: int32(gemPortID), // GemportId not used
3282 Classifier: classifierProto,
3283 Action: actionProto,
3284 Priority: int32(logicalFlow.Priority),
3285 Cookie: logicalFlow.Cookie,
3286 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003287 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003288 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003289 }
Shrey Baid26912972020-04-16 21:02:31 +05303290 logger.Info("igmp-trap-on-nni-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003291 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3292 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3293 int32(onuID),
3294 int32(uniID),
3295 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003296 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003297 }
3298 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003299}
3300
salmansiddiqui7ac62132019-08-22 03:58:50 +00003301func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
3302 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05303303 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003304 }
3305 if Dir == tp_pb.Direction_UPSTREAM {
3306 return "upstream", nil
3307 } else if Dir == tp_pb.Direction_DOWNSTREAM {
3308 return "downstream", nil
3309 }
3310 return "", nil
3311}
3312
npujarec5762e2020-01-01 14:08:48 +05303313func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00003314 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003315 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00003316 var gemPort uint32
3317 intfID := args[IntfID]
3318 onuID := args[OnuID]
3319 uniID := args[UniID]
3320 portNo := args[PortNo]
3321 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00003322 if ipProto, ok := classifierInfo[IPProto]; ok {
3323 if ipProto.(uint32) == IPProtoDhcp {
Shrey Baid26912972020-04-16 21:02:31 +05303324 logger.Info("adding-dhcp-flow")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003325 if pcp, ok := classifierInfo[VlanPcp]; ok {
3326 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3327 tp_pb.Direction_UPSTREAM,
3328 pcp.(uint32))
3329 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00003330
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003331 f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003332 } else {
3333 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003334 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003335 }
3336
Girish Gowdra32625212020-04-29 11:26:35 -07003337 } else if ipProto.(uint32) == IgmpProto {
Shrey Baid26912972020-04-16 21:02:31 +05303338 logger.Infow("adding-us-igmp-flow",
3339 log.Fields{
3340 "intf-id": intfID,
3341 "onu-id": onuID,
3342 "uni-id": uniID,
3343 "classifier-info:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003344 if pcp, ok := classifierInfo[VlanPcp]; ok {
3345 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3346 tp_pb.Direction_UPSTREAM,
3347 pcp.(uint32))
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003348 f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003349 } else {
3350 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003351 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003352 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003353 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303354 logger.Errorw("invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003355 return
3356 }
3357 } else if ethType, ok := classifierInfo[EthType]; ok {
3358 if ethType.(uint32) == EapEthType {
Shrey Baid26912972020-04-16 21:02:31 +05303359 logger.Info("adding-eapol-flow")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003360 var vlanID uint32
3361 if val, ok := classifierInfo[VlanVid]; ok {
3362 vlanID = (val.(uint32)) & VlanvIDMask
3363 } else {
3364 vlanID = DefaultMgmtVlan
3365 }
3366 if pcp, ok := classifierInfo[VlanPcp]; ok {
3367 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3368 tp_pb.Direction_UPSTREAM,
3369 pcp.(uint32))
3370
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003371 f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003372 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003373 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003374 }
3375 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003376 } else if _, ok := actionInfo[PushVlan]; ok {
Shrey Baid26912972020-04-16 21:02:31 +05303377 logger.Info("adding-upstream-data-rule")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003378 if pcp, ok := classifierInfo[VlanPcp]; ok {
3379 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3380 tp_pb.Direction_UPSTREAM,
3381 pcp.(uint32))
3382 //Adding HSIA upstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003383 f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003384 } else {
3385 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003386 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003387 }
3388 } else if _, ok := actionInfo[PopVlan]; ok {
Shrey Baid26912972020-04-16 21:02:31 +05303389 logger.Info("adding-downstream-data-rule")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003390 if pcp, ok := classifierInfo[VlanPcp]; ok {
3391 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05003392 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003393 pcp.(uint32))
3394 //Adding HSIA downstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003395 f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003396 } else {
3397 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003398 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003399 }
3400 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303401 logger.Errorw("invalid-flow-type-to-handle",
3402 log.Fields{
3403 "classifier": classifierInfo,
3404 "action": actionInfo,
3405 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003406 return
3407 }
3408 // Send Techprofile download event to child device in go routine as it takes time
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003409 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003410}
3411
Gamze Abakafee36392019-10-03 11:17:24 +00003412func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
3413 flowIDList := f.flowsUsedByGemPort[gemPK]
3414 if len(flowIDList) > 1 {
3415 return true
3416 }
3417 return false
3418}
3419
npujarec5762e2020-01-01 14:08:48 +05303420func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3421 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003422 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3423 for _, currentGemPort := range currentGemPorts {
3424 for _, tpGemPort := range tpGemPorts {
3425 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3426 return true, currentGemPort
3427 }
3428 }
3429 }
Girish Gowdra54934262019-11-13 14:19:55 +05303430 if tpInst.InstanceCtrl.Onu == "single-instance" {
3431 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
npujarec5762e2020-01-01 14:08:48 +05303432 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID)
3433 f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID)
Girish Gowdra54934262019-11-13 14:19:55 +05303434
3435 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3436 // still be used on other uni ports.
3437 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3438 // on any other uni port.
npujarec5762e2020-01-01 14:08:48 +05303439 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID)
Shrey Baid26912972020-04-16 21:02:31 +05303440 logger.Debugw("got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303441 for i := 0; i < len(tpInstances); i++ {
3442 tpI := tpInstances[i]
3443 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303444 for _, tpGemPort := range tpGemPorts {
3445 if tpGemPort.GemportID != gemPortID {
Shrey Baid26912972020-04-16 21:02:31 +05303446 logger.Debugw("single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303447 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303448 }
3449 }
3450 }
3451 }
Shrey Baid26912972020-04-16 21:02:31 +05303452 logger.Debug("tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003453 return false, 0
3454}
3455
salmansiddiqui7ac62132019-08-22 03:58:50 +00003456func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003457 for _, field := range flows.GetOfbFields(flow) {
3458 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003459 classifierInfo[EthType] = field.GetEthType()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003460 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003461 } else if field.Type == flows.ETH_DST {
3462 classifierInfo[EthDst] = field.GetEthDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003463 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003464 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003465 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003466 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003467 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003468 classifierInfo[InPort] = field.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003469 logger.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003470 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303471 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00003472 logger.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003473 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003474 classifierInfo[VlanPcp] = field.GetVlanPcp()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003475 logger.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003476 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003477 classifierInfo[UDPDst] = field.GetUdpDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003478 logger.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003479 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003480 classifierInfo[UDPSrc] = field.GetUdpSrc()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003481 logger.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003482 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003483 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003484 logger.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003485 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003486 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003487 logger.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003488 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003489 classifierInfo[Metadata] = field.GetTableMetadata()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003490 logger.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003491 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003492 classifierInfo[TunnelID] = field.GetTunnelId()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003493 logger.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003494 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303495 logger.Errorw("un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003496 return
3497 }
3498 }
3499}
3500
3501func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003502 for _, action := range flows.GetActions(flow) {
3503 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003504 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003505 actionInfo[Output] = out.GetPort()
Shrey Baid26912972020-04-16 21:02:31 +05303506 logger.Debugw("action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003507 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003508 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003509 }
Scott Baker355d1742019-10-24 10:57:52 -07003510 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003511 actionInfo[PopVlan] = true
Girish Kumar2ad402b2020-03-20 19:45:12 +00003512 logger.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003513 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003514 if out := action.GetPush(); out != nil {
3515 if tpid := out.GetEthertype(); tpid != 0x8100 {
Shrey Baid26912972020-04-16 21:02:31 +05303516 logger.Errorw("invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003517 } else {
3518 actionInfo[PushVlan] = true
3519 actionInfo[TPID] = tpid
Girish Kumar2ad402b2020-03-20 19:45:12 +00003520 logger.Debugw("action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303521 log.Fields{
3522 "push-tpid": actionInfo[TPID].(uint32),
3523 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003524 }
3525 }
Scott Baker355d1742019-10-24 10:57:52 -07003526 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003527 if out := action.GetSetField(); out != nil {
3528 if field := out.GetField(); field != nil {
3529 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003530 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003531 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00003532 /*logger.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
Esin Karamanccb714b2019-11-29 15:02:06 +00003533 formulateSetFieldActionInfoFromFlow(field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003534 }
3535 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003536 } else if action.Type == flows.GROUP {
3537 formulateGroupActionInfoFromFlow(action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003538 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003539 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003540 }
3541 }
3542 return nil
3543}
3544
Esin Karamanccb714b2019-11-29 15:02:06 +00003545func formulateSetFieldActionInfoFromFlow(field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
3546 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003547 fieldtype := ofbField.GetType()
3548 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003549 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3550 actionInfo[VlanVid] = vlan & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00003551 logger.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003552 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303553 logger.Error("no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003554 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003555 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3556 pcp := ofbField.GetVlanPcp()
3557 actionInfo[VlanPcp] = pcp
3558 log.Debugw("action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003559 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003560 logger.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003561 }
3562 }
3563}
3564
3565func formulateGroupActionInfoFromFlow(action *ofp.OfpAction, actionInfo map[string]interface{}) {
3566 if action.GetGroup() == nil {
Shrey Baid26912972020-04-16 21:02:31 +05303567 logger.Warn("no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003568 } else {
3569 actionInfo[GroupID] = action.GetGroup().GroupId
Girish Kumar2ad402b2020-03-20 19:45:12 +00003570 logger.Debugw("action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003571 }
3572}
3573
salmansiddiqui7ac62132019-08-22 03:58:50 +00003574func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003575 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Shrey Baid26912972020-04-16 21:02:31 +05303576 logger.Debug("controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003577 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3578 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003579 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003580 classifierInfo[InPort] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303581 logger.Debugw("upstream-pon-to-controller-flow--inport-in-tunnelid",
3582 log.Fields{
3583 "newinport": classifierInfo[InPort].(uint32),
3584 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003585 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303586 return olterrors.NewErrNotFound("child-in-port",
3587 log.Fields{
3588 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3589 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003590 }
3591 }
3592 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303593 logger.Debug("non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003594 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003595 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003596 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003597 actionInfo[Output] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303598 logger.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid",
3599 log.Fields{
3600 "newoutport": actionInfo[Output].(uint32),
3601 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003602 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303603 return olterrors.NewErrNotFound("out-port",
3604 log.Fields{
3605 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3606 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003607 }
3608 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3609 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003610 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003611 classifierInfo[InPort] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303612 logger.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid",
3613 log.Fields{
3614 "newinport": actionInfo[Output].(uint32),
3615 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003616 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303617 return olterrors.NewErrNotFound("nni-port",
3618 log.Fields{
3619 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3620 "in-port": classifierInfo[InPort].(uint32),
3621 "out-port": actionInfo[Output].(uint32),
3622 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003623 }
3624 }
3625 }
3626 return nil
3627}
Gamze Abakafee36392019-10-03 11:17:24 +00003628
Chaitrashree G S90a17952019-11-14 21:51:21 -05003629func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003630 /* Metadata 8 bytes:
3631 Most Significant 2 Bytes = Inner VLAN
3632 Next 2 Bytes = Tech Profile ID(TPID)
3633 Least Significant 4 Bytes = Port ID
3634 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3635 subscriber related flows.
3636 */
3637 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
3638 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003639 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003640 }
3641 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003642 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003643}
3644
3645func appendUnique(slice []uint32, item uint32) []uint32 {
3646 for _, sliceElement := range slice {
3647 if sliceElement == item {
3648 return slice
3649 }
3650 }
3651 return append(slice, item)
3652}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303653
3654// getNniIntfID gets nni intf id from the flow classifier/action
3655func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
3656
3657 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3658 if portType == voltha.Port_PON_OLT {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003659 intfID, err := IntfIDFromNniPortNum(action[Output].(uint32))
3660 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003661 logger.Debugw("invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003662 log.Fields{
3663 "port-number": action[Output].(uint32),
3664 "error": err})
3665 return uint32(0), err
3666 }
Shrey Baid26912972020-04-16 21:02:31 +05303667 logger.Infow("output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303668 return intfID, nil
3669 } else if portType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003670 intfID, err := IntfIDFromNniPortNum(classifier[InPort].(uint32))
3671 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003672 logger.Debugw("invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003673 log.Fields{
3674 "port-number": action[Output].(uint32),
3675 "error": err})
3676 return uint32(0), err
3677 }
Shrey Baid26912972020-04-16 21:02:31 +05303678 logger.Infow("input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303679 return intfID, nil
3680 }
3681 return uint32(0), nil
3682}
3683
3684// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
npujarec5762e2020-01-01 14:08:48 +05303685func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303686 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
3687
3688 f.lockCache.Lock()
3689 defer f.lockCache.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003690 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303691 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003692 if lookupGemPort == gemPort {
Shrey Baid26912972020-04-16 21:02:31 +05303693 logger.Infow("pktin-key/value-found-in-cache--no-need-to-update-kv--assume-both-in-sync",
3694 log.Fields{
3695 "pktinkey": pktInkey,
3696 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003697 return
3698 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303699 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003700 f.packetInGemPort[pktInkey] = gemPort
3701
npujarec5762e2020-01-01 14:08:48 +05303702 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Shrey Baid26912972020-04-16 21:02:31 +05303703 logger.Infow("pktin-key-not-found-in-local-cache-value-is-different--updating-cache-and-kv-store",
3704 log.Fields{
3705 "pktinkey": pktInkey,
3706 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303707 return
3708}
3709
3710// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303711func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303712 f.lockCache.Lock()
3713 defer f.lockCache.Unlock()
3714 onugem := f.onuGemInfo[intfID]
3715 for idx, onu := range onugem {
3716 if onu.OnuID == onuID {
3717 for _, uni := range onu.UniPorts {
3718 if uni == portNum {
Shrey Baid26912972020-04-16 21:02:31 +05303719 logger.Infow("uni-already-in-cache--no-need-to-update-cache-and-kv-store", log.Fields{"uni": portNum})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303720 return
3721 }
3722 }
3723 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3724 f.onuGemInfo[intfID] = onugem
3725 }
3726 }
npujarec5762e2020-01-01 14:08:48 +05303727 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303728}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303729
npujarec5762e2020-01-01 14:08:48 +05303730func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3731 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303732 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303733 logger.Error("failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303734 return
3735 }
3736 for gem, FlowIDs := range flowIDsList {
3737 gemPK := gemPortKey{intf, uint32(gem)}
3738 f.flowsUsedByGemPort[gemPK] = FlowIDs
3739 }
3740 return
3741}
Esin Karamanccb714b2019-11-29 15:02:06 +00003742
3743//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
3744//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05303745func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
3746 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00003747 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303748 logger.Error("failed-to-get-pon-interface-to-multicast-queue-map")
Esin Karamanccb714b2019-11-29 15:02:06 +00003749 return
3750 }
3751 for intf, queueInfo := range storedMulticastQueueMap {
3752 q := queueInfoBrief{
3753 gemPortID: queueInfo[0],
3754 servicePriority: queueInfo[1],
3755 }
3756 f.interfaceToMcastQueueMap[intf] = &q
3757 }
3758}
3759
3760//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
3761//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
3762//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05303763func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
3764 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00003765 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003766 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00003767 }
3768 if exists {
3769 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
3770 }
3771 return nil, exists, nil
3772}
3773
3774func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
3775 groupDesc := ofp.OfpGroupDesc{
3776 Type: ofp.OfpGroupType_OFPGT_ALL,
3777 GroupId: groupID,
3778 }
3779 groupEntry := ofp.OfpGroupEntry{
3780 Desc: &groupDesc,
3781 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003782 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003783 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00003784 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003785 bucket := ofp.OfpBucket{
3786 Actions: acts,
3787 }
3788 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00003789 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003790 return &groupEntry
3791}