blob: 336babcae66d611b2f96677e6f2040002d892871 [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
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700202 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000203 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
Matteo Scandoloac032b12020-08-03 11:14:22 -0700218 perGemPortLock *mapmutex.Mutex // lock to be used to access the flowsUsedByGemPort map
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530219 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
220 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700221 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Matteo Scandolo60913ed2020-06-23 19:31:14 -0700222 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache, indexed by IntfId
223 // We need to have a global lock on the onuGemInfo map
224 onuGemInfoLock sync.RWMutex
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700225 pendingFlowDelete sync.Map
Girish Gowdra3d633032019-12-10 16:37:05 +0530226 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Esin Karamanccb714b2019-11-29 15:02:06 +0000227 perUserFlowHandleLock *mapmutex.Mutex
228 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 +0530229}
230
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700231//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
npujarec5762e2020-01-01 14:08:48 +0530232func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
Shrey Baid26912972020-04-16 21:02:31 +0530233 logger.Infow("initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530234 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530235 var err error
236 var idx uint32
237
manikkaraj kbf256be2019-03-25 00:13:48 +0530238 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530239 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000240 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530241 if err = flowMgr.populateTechProfilePerPonPort(); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530242 logger.Errorw("error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530243 return nil
244 }
William Kurkian740a09c2019-10-23 17:07:38 -0400245 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530246 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
247 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530248 ponPorts := rMgr.DevInfo.GetPonPorts()
Matteo Scandolo60913ed2020-06-23 19:31:14 -0700249 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo, ponPorts)
Girish Gowdra8e43ebb2020-08-17 15:41:16 -0700250 flowMgr.onuGemInfoLock = sync.RWMutex{}
251 flowMgr.pendingFlowDelete = sync.Map{}
252 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(300, 100000000, 10000000, 1.1, 0.2)
253 flowMgr.perGemPortLock = mapmutex.NewCustomizedMapMutex(300, 100000000, 10000000, 1.1, 0.2)
254 flowMgr.interfaceToMcastQueueMap = make(map[uint32]*queueInfoBrief)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530255 //Load the onugem info cache from kv store on flowmanager start
256 for idx = 0; idx < ponPorts; idx++ {
npujarec5762e2020-01-01 14:08:48 +0530257 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530258 logger.Error("failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530259 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530260 //Load flowID list per gem map per interface from the kvstore.
npujarec5762e2020-01-01 14:08:48 +0530261 flowMgr.loadFlowIDlistForGem(ctx, idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530262 }
Esin Karamanccb714b2019-11-29 15:02:06 +0000263 //load interface to multicast queue map from kv store
npujarec5762e2020-01-01 14:08:48 +0530264 flowMgr.loadInterfaceToMulticastQueueMap(ctx)
Shrey Baid26912972020-04-16 21:02:31 +0530265 logger.Info("initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530266 return &flowMgr
267}
268
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700269func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700270 if direction == Upstream {
Shrey Baid26912972020-04-16 21:02:31 +0530271 logger.Debugw("upstream-flow-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700272 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700273 } else if direction == Downstream {
Shrey Baid26912972020-04-16 21:02:31 +0530274 logger.Debugw("downstream-flow-not-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700275 return uint64(flowID), nil
Esin Karamanccb714b2019-11-29 15:02:06 +0000276 } else if direction == Multicast {
Shrey Baid26912972020-04-16 21:02:31 +0530277 logger.Debugw("multicast-flow-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000278 return 0x2<<15 | uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400279 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530280 return 0, olterrors.NewErrInvalidValue(log.Fields{"direction": direction}, nil).Log()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400281 }
282}
283
npujarec5762e2020-01-01 14:08:48 +0530284func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Matteo Scandoloac032b12020-08-03 11:14:22 -0700285
Gamze Abakafee36392019-10-03 11:17:24 +0000286 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
Matteo Scandoloac032b12020-08-03 11:14:22 -0700287 if f.perGemPortLock.TryLock(gemPK) {
288 logger.Debugw("registering-flow-for-device",
289 log.Fields{
290 "flow": flowFromCore,
291 "device-id": f.deviceHandler.device.Id})
292 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
293 if !ok {
294 flowIDList = []uint32{deviceFlow.FlowId}
295 }
296 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
297 f.flowsUsedByGemPort[gemPK] = flowIDList
298 // update the flowids for a gem to the KVstore
299 f.resourceMgr.UpdateFlowIDsForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
300 f.perGemPortLock.Unlock(gemPK)
301 } else {
302 logger.Error("failed-to-acquire-per-gem-port-lock",
303 log.Fields{
304 "flow": flowFromCore,
305 "device-id": f.deviceHandler.device.Id,
306 "key": gemPK,
307 })
Gamze Abakafee36392019-10-03 11:17:24 +0000308 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400309}
310
npujarec5762e2020-01-01 14:08:48 +0530311func (f *OpenOltFlowMgr) divideAndAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000312 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
313 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000314 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530315 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700316 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530317
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700318 logger.Infow("dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530319 "device-id": f.deviceHandler.device.Id,
320 "intf-id": intfID,
321 "onu-id": onuID,
322 "uni-id": uniID,
323 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700324 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530325 "action": actionInfo,
326 "usmeter-iD": UsMeterID,
327 "dsmeter-iD": DsMeterID,
328 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400329 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
330 // is because the flow is an NNI flow and there would be no onu resources associated with it
331 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400332 if onuID <= 0 {
Shrey Baid26912972020-04-16 21:02:31 +0530333 logger.Errorw("no-onu-id-for-flow",
334 log.Fields{
335 "port-no": portNo,
336 "classifer": classifierInfo,
337 "action": actionInfo,
338 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530339 return
340 }
341
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700342 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Shrey Baid26912972020-04-16 21:02:31 +0530343 logger.Debugw("uni-port-path", log.Fields{
344 "uni": uni,
345 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530346
347 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
348 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700349 logger.Debugw("dividing-flow-create-tcont-gem-ports", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530350 "device-id": f.deviceHandler.device.Id,
351 "intf-id": intfID,
352 "onu-id": onuID,
353 "uni-id": uniID,
354 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700355 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530356 "action": actionInfo,
357 "usmeter-id": UsMeterID,
358 "dsmeter-id": DsMeterID,
359 "tp-id": TpID})
npujarec5762e2020-01-01 14:08:48 +0530360 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530361 if allocID == 0 || gemPorts == nil || TpInst == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000362 logger.Error("alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530363 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
364 return
365 }
366 args := make(map[string]uint32)
367 args[IntfID] = intfID
368 args[OnuID] = onuID
369 args[UniID] = uniID
370 args[PortNo] = portNo
371 args[AllocID] = allocID
372
373 /* Flows can be added specific to gemport if p-bits are received.
374 * If no pbit mentioned then adding flows for all gemports
375 */
npujarec5762e2020-01-01 14:08:48 +0530376 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530377 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
378 } else {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700379 logger.Errorw("failed-to-acquire-per-user-flow-handle-lock",
Shrey Baid26912972020-04-16 21:02:31 +0530380 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700381 "intf-id": intfID,
382 "onu-id": onuID,
383 "uni-id": uniID,
384 "flow-id": flow.Id,
385 "flow-cookie": flow.Cookie,
386 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400387 return
388 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530389}
390
salmansiddiqui7ac62132019-08-22 03:58:50 +0000391// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530392func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400393
Shrey Baid26912972020-04-16 21:02:31 +0530394 logger.Debugw("CreateSchedulerQueues",
395 log.Fields{"dir": sq.direction,
396 "intf-id": sq.intfID,
397 "onu-id": sq.onuID,
398 "uni-id": sq.uniID,
399 "tp-id": sq.tpID,
400 "meter-id": sq.meterID,
401 "tp-inst": sq.tpInst,
402 "flowmetadata": sq.flowMetadata,
403 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400404
Gamze Abakafee36392019-10-03 11:17:24 +0000405 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000406 if err != nil {
407 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400408 }
409
410 /* Lets make a simple assumption that if the meter-id is present on the KV store,
411 * then the scheduler and queues configuration is applied on the OLT device
412 * in the given direction.
413 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000414
Manikkaraj kb1d51442019-07-23 10:41:02 -0400415 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530416 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400417 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530418 return olterrors.NewErrNotFound("meter",
419 log.Fields{"intf-id": sq.intfID,
420 "onu-id": sq.onuID,
421 "uni-id": sq.uniID,
422 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400423 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000424
Manikkaraj kb1d51442019-07-23 10:41:02 -0400425 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000426 if KvStoreMeter.MeterId == sq.meterID {
Shrey Baid26912972020-04-16 21:02:31 +0530427 logger.Debugw("scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400428 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400429 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530430 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800431 "unsupported": "meter-id",
432 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530433 "meter-id-in-flow": sq.meterID,
434 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400435 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000436
Shrey Baid26912972020-04-16 21:02:31 +0530437 logger.Debugw("meter-does-not-exist-creating-new",
438 log.Fields{
439 "meter-id": sq.meterID,
440 "direction": Direction,
441 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000442
Gamze Abakafee36392019-10-03 11:17:24 +0000443 if sq.direction == tp_pb.Direction_UPSTREAM {
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700444 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000445 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700446 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400447 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000448
449 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530450 return olterrors.NewErrNotFound("scheduler-config",
451 log.Fields{
452 "intf-id": sq.intfID,
453 "direction": sq.direction,
454 "tp-inst": sq.tpInst,
455 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000456 }
457
Manikkaraj kb1d51442019-07-23 10:41:02 -0400458 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000459 if sq.flowMetadata != nil {
460 for _, meter := range sq.flowMetadata.Meters {
461 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400462 meterConfig = meter
Shrey Baid26912972020-04-16 21:02:31 +0530463 logger.Debugw("found-meter-config-from-flowmetadata",
464 log.Fields{"meterConfig": meterConfig,
465 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400466 break
467 }
468 }
469 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530470 logger.Errorw("flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400471 }
472 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530473 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800474 "reason": "Could-not-get-meterbands-from-flowMetadata",
475 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530476 "meter-id": sq.meterID,
477 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478 } else if len(meterConfig.Bands) < MaxMeterBand {
Shrey Baid26912972020-04-16 21:02:31 +0530479 logger.Errorw("invalid-number-of-bands-in-meter",
480 log.Fields{"Bands": meterConfig.Bands,
481 "meter-id": sq.meterID,
482 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530483 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800484 "reason": "Invalid-number-of-bands-in-meter",
485 "meterband-count": len(meterConfig.Bands),
486 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530487 "meter-id": sq.meterID,
488 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400489 }
490 cir := meterConfig.Bands[0].Rate
491 cbs := meterConfig.Bands[0].BurstSize
492 eir := meterConfig.Bands[1].Rate
493 ebs := meterConfig.Bands[1].BurstSize
494 pir := cir + eir
495 pbs := cbs + ebs
496 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
497
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700498 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000499 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400500
npujarec5762e2020-01-01 14:08:48 +0530501 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530502 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
503 log.Fields{"intf-id": sq.intfID,
504 "direction": sq.direction,
505 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400506 }
507
salmansiddiqui7ac62132019-08-22 03:58:50 +0000508 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400509 * store the meter id on the KV store, for further reference.
510 */
npujarec5762e2020-01-01 14:08:48 +0530511 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 +0530512 return olterrors.NewErrAdapter("failed-updating-meter-id",
513 log.Fields{"onu-id": sq.onuID,
514 "meter-id": sq.meterID,
515 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400516 }
Shrey Baid26912972020-04-16 21:02:31 +0530517 logger.Infow("updated-meter-info-into-kv-store-successfully",
518 log.Fields{"direction": Direction,
519 "Meter": meterConfig,
520 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400521 return nil
522}
523
npujarec5762e2020-01-01 14:08:48 +0530524func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000525
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700526 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000527
528 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530529 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
530 log.Fields{"intf-id": sq.intfID,
531 "direction": sq.direction,
532 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000533 }
534
Shrey Baid26912972020-04-16 21:02:31 +0530535 logger.Debugw("sending-traffic-scheduler-create-to-device",
536 log.Fields{
537 "direction": sq.direction,
538 "TrafficScheds": TrafficSched,
539 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530540 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000541 IntfId: sq.intfID, OnuId: sq.onuID,
542 UniId: sq.uniID, PortNo: sq.uniPort,
543 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000544 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000545 }
Shrey Baid26912972020-04-16 21:02:31 +0530546 logger.Infow("successfully-created-traffic-schedulers", log.Fields{
547 "direction": sq.direction,
548 "traffic-queues": trafficQueues,
549 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000550
551 // On receiving the CreateTrafficQueues request, the driver should create corresponding
552 // downstream queues.
Shrey Baid26912972020-04-16 21:02:31 +0530553 logger.Debugw("sending-traffic-queues-create-to-device",
554 log.Fields{"direction": sq.direction,
555 "traffic-queues": trafficQueues,
556 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530557 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000558 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
559 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000560 TrafficQueues: trafficQueues,
561 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530562 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000563 }
Shrey Baid26912972020-04-16 21:02:31 +0530564 logger.Infow("successfully-created-traffic-schedulers", log.Fields{
565 "direction": sq.direction,
566 "traffic-queues": trafficQueues,
567 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000568
Esin Karamanccb714b2019-11-29 15:02:06 +0000569 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700570 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000571 if len(multicastTrafficQueues) > 0 {
572 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
573 //assumed that there is only one queue per PON for the multicast service
574 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
575 //just put it in interfaceToMcastQueueMap to use for building group members
Shrey Baid26912972020-04-16 21:02:31 +0530576 logger.Debugw("multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000577 multicastQueuePerPonPort := multicastTrafficQueues[0]
578 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
579 gemPortID: multicastQueuePerPonPort.GemportId,
580 servicePriority: multicastQueuePerPonPort.Priority,
581 }
582 //also store the queue info in kv store
npujarec5762e2020-01-01 14:08:48 +0530583 f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID,
Esin Karamanccb714b2019-11-29 15:02:06 +0000584 multicastQueuePerPonPort.GemportId,
585 multicastQueuePerPonPort.Priority)
Shrey Baid26912972020-04-16 21:02:31 +0530586
587 logger.Infow("multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000588 }
589 }
590 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000591 return nil
592}
593
salmansiddiqui7ac62132019-08-22 03:58:50 +0000594// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530595func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400596
597 var Direction string
598 var SchedCfg *tp_pb.SchedulerConfig
599 var err error
Shrey Baid26912972020-04-16 21:02:31 +0530600 logger.Infow("removing-schedulers-and-queues-in-olt",
601 log.Fields{
602 "direction": sq.direction,
603 "intf-id": sq.intfID,
604 "onu-id": sq.onuID,
605 "uni-id": sq.uniID,
606 "uni-port": sq.uniPort,
607 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000608 if sq.direction == tp_pb.Direction_UPSTREAM {
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700609 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400610 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000611 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700612 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400613 Direction = "downstream"
614 }
615
Girish Kumar8f73fe02019-12-09 13:19:37 +0000616 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530617 return olterrors.NewErrNotFound("scheduler-config",
618 log.Fields{
619 "int-id": sq.intfID,
620 "direction": sq.direction,
621 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000622 }
623
npujarec5762e2020-01-01 14:08:48 +0530624 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400625 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530626 return olterrors.NewErrNotFound("meter",
627 log.Fields{
628 "onu-id": sq.onuID,
629 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400630 }
631 if KVStoreMeter == nil {
Shrey Baid26912972020-04-16 21:02:31 +0530632 logger.Warnw("no-meter-installed-yet",
633 log.Fields{
634 "direction": Direction,
635 "intf-id": sq.intfID,
636 "onu-id": sq.onuID,
637 "uni-id": sq.uniID,
638 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400639 return nil
640 }
641 cir := KVStoreMeter.Bands[0].Rate
642 cbs := KVStoreMeter.Bands[0].BurstSize
643 eir := KVStoreMeter.Bands[1].Rate
644 ebs := KVStoreMeter.Bands[1].BurstSize
645 pir := cir + eir
646 pbs := cbs + ebs
647
648 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
649
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700650 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000651 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000652
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700653 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000654 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530655 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
656 log.Fields{
657 "intf-id": sq.intfID,
658 "direction": sq.direction,
659 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000660 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400661
npujarec5762e2020-01-01 14:08:48 +0530662 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000663 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
664 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000665 TrafficQueues: TrafficQueues,
666 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000667 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530668 log.Fields{
669 "intf-id": sq.intfID,
670 "traffic-queues": TrafficQueues,
671 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400672 }
Shrey Baid26912972020-04-16 21:02:31 +0530673 logger.Infow("removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530674 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000675 IntfId: sq.intfID, OnuId: sq.onuID,
676 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400677 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000678 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530679 log.Fields{
680 "intf-id": sq.intfID,
681 "traffic-schedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400682 }
683
Shrey Baid26912972020-04-16 21:02:31 +0530684 logger.Infow("removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000685
686 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400687 * delete the meter id on the KV store.
688 */
npujarec5762e2020-01-01 14:08:48 +0530689 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400690 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530691 return olterrors.NewErrAdapter("unable-to-remove-meter",
692 log.Fields{
693 "onu": sq.onuID,
694 "meter": KVStoreMeter.MeterId,
695 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400696 }
Shrey Baid26912972020-04-16 21:02:31 +0530697 logger.Infow("removed-meter-from-KV-store-successfully",
698 log.Fields{
699 "meter-id": KVStoreMeter.MeterId,
700 "dir": Direction,
701 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400702 return err
703}
704
Gamze Abakafee36392019-10-03 11:17:24 +0000705// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700706func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) (uint32, []uint32, interface{}) {
Gamze Abakafee36392019-10-03 11:17:24 +0000707 var allocIDs []uint32
708 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530709 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530710 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000711 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000712
npujarec5762e2020-01-01 14:08:48 +0530713 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
714 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400715
716 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530717
Shrey Baid26912972020-04-16 21:02:31 +0530718 logger.Debugw("creating-new-tcont-and-gem", log.Fields{
719 "intf-id": intfID,
720 "onu-id": onuID,
721 "uni-id": uniID,
722 "device-id": f.deviceHandler.device.Id,
723 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530724
Manikkaraj kb1d51442019-07-23 10:41:02 -0400725 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530726 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000727 if techProfileInstance == nil {
Shrey Baid26912972020-04-16 21:02:31 +0530728 logger.Infow("tp-instance-not-found--creating-new",
729 log.Fields{
730 "path": tpPath,
731 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530732 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000733 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530734 // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +0530735 logger.Errorw("tp-instance-create-failed",
736 log.Fields{
737 "error": err,
738 "tp-id": TpID,
739 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000740 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530741 }
npujarec5762e2020-01-01 14:08:48 +0530742 f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530743 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530744 logger.Debugw("tech-profile-instance-already-exist-for-given port-name",
745 log.Fields{
746 "uni": uni,
747 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530748 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530749 }
Gamze Abakafee36392019-10-03 11:17:24 +0000750
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700751 switch tpInst := techProfileInstance.(type) {
752 case *tp.TechProfile:
753 if UsMeterID != 0 {
754 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
755 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
756 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
757 logger.Errorw("CreateSchedulerQueues-failed-upstream",
758 log.Fields{
759 "error": err,
760 "meter-id": UsMeterID,
761 "device-id": f.deviceHandler.device.Id})
762 return 0, nil, nil
763 }
764 }
765 if DsMeterID != 0 {
766 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
767 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
768 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
769 logger.Errorw("CreateSchedulerQueues-failed-downstream",
770 log.Fields{
771 "error": err,
772 "meter-id": DsMeterID,
773 "device-id": f.deviceHandler.device.Id})
774 return 0, nil, nil
775 }
776 }
777 allocID := tpInst.UsScheduler.AllocID
778 for _, gem := range tpInst.UpstreamGemPortAttributeList {
779 gemPortIDs = append(gemPortIDs, gem.GemportID)
780 }
781 allocIDs = appendUnique(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000782
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700783 if tpInstanceExists {
784 return allocID, gemPortIDs, techProfileInstance
785 }
786
787 for _, gemPortID := range gemPortIDs {
788 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
789 }
790 logger.Infow("allocated-tcont-and-gem-ports",
791 log.Fields{
792 "alloc-ids": allocIDs,
793 "gemports": allgemPortIDs,
794 "device-id": f.deviceHandler.device.Id})
795 // Send Tconts and GEM ports to KV store
796 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530797 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700798 case *tp.EponProfile:
799 // CreateSchedulerQueues for EPON needs to be implemented here
800 // when voltha-protos for EPON is completed.
801 allocID := tpInst.AllocID
802 for _, gem := range tpInst.UpstreamQueueAttributeList {
803 gemPortIDs = append(gemPortIDs, gem.GemportID)
804 }
805 allocIDs = appendUnique(allocIDs, allocID)
806
807 if tpInstanceExists {
808 return allocID, gemPortIDs, techProfileInstance
809 }
810
811 for _, gemPortID := range gemPortIDs {
812 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
813 }
814 logger.Infow("allocated-tcont-and-gem-ports",
815 log.Fields{
816 "alloc-ids": allocIDs,
817 "gemports": allgemPortIDs,
818 "device-id": f.deviceHandler.device.Id})
819 // Send Tconts and GEM ports to KV store
820 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
821 return allocID, gemPortIDs, techProfileInstance
822 default:
823 logger.Errorw("unknown-tech",
824 log.Fields{
825 "tpInst": tpInst})
826 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530827 }
828
manikkaraj kbf256be2019-03-25 00:13:48 +0530829}
830
npujarec5762e2020-01-01 14:08:48 +0530831func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530832
Shrey Baid26912972020-04-16 21:02:31 +0530833 logger.Debugw("storing-allocated-tconts-and-gem-ports-into-KV-store",
834 log.Fields{
835 "intf-id": intfID,
836 "onu-id": onuID,
837 "uni-id": uniID,
838 "alloc-id": allocID,
839 "gemport-ids": gemPortIDs,
840 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530841 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530842 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530843 logger.Errorw("error-while-uploading-allocid-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530844 }
npujarec5762e2020-01-01 14:08:48 +0530845 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530846 logger.Errorw("error-while-uploading-gemports-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530847 }
npujarec5762e2020-01-01 14:08:48 +0530848 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530849 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 +0530850 }
Shrey Baid26912972020-04-16 21:02:31 +0530851 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 -0400852 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530853 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400854 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530855}
856
857func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000858 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530859 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000860 for _, intfID := range techRange.IntfIds {
861 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400862 tpCount++
Shrey Baid26912972020-04-16 21:02:31 +0530863 logger.Debugw("init-tech-profile-done",
864 log.Fields{
865 "intf-id": intfID,
866 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530867 }
868 }
869 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400870 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530871 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530872 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800873 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530874 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
875 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530876 }
Shrey Baid26912972020-04-16 21:02:31 +0530877 logger.Infow("populated-techprofile-for-ponports-successfully",
878 log.Fields{
879 "numofTech": tpCount,
880 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
881 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530882 return nil
883}
884
npujarec5762e2020-01-01 14:08:48 +0530885func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530886 portNo uint32, uplinkClassifier map[string]interface{},
887 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000888 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700889 uplinkClassifier[PacketTagType] = SingleTag
Shrey Baid26912972020-04-16 21:02:31 +0530890 logger.Debugw("adding-upstream-data-flow",
891 log.Fields{
892 "uplinkClassifier": uplinkClassifier,
893 "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800894 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000895 Upstream, logicalFlow, allocID, gemportID, tpID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530896 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530897}
898
npujarec5762e2020-01-01 14:08:48 +0530899func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530900 portNo uint32, downlinkClassifier map[string]interface{},
901 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000902 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700903 downlinkClassifier[PacketTagType] = DoubleTag
Shrey Baid26912972020-04-16 21:02:31 +0530904 logger.Debugw("adding-downstream-data-flow",
905 log.Fields{
906 "downlinkClassifier": downlinkClassifier,
907 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400908 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
909 if vlan, exists := downlinkClassifier[VlanVid]; exists {
910 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700911 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400912 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
Shrey Baid26912972020-04-16 21:02:31 +0530913 logger.Infow("ignoring-dl-trap-device-flow-from-core",
914 log.Fields{
915 "flow": logicalFlow,
916 "device-id": f.deviceHandler.device.Id,
917 "onu-id": onuID,
918 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800919 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400920 }
921 }
922 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530923 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400924
Manikkaraj k884c1242019-04-11 16:26:42 +0530925 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700926 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400927 // vlan_vid is a uint32. must be type asserted as such or conversion fails
928 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530929 if ok {
930 downlinkAction[VlanVid] = dlClVid & 0xfff
931 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530932 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530933 "reason": "failed-to-convert-vlanid-classifier",
934 "vlan-id": VlanVid,
935 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530936 }
937
David K. Bainbridge794735f2020-02-11 21:01:37 -0800938 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000939 Downstream, logicalFlow, allocID, gemportID, tpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530940}
941
npujarec5762e2020-01-01 14:08:48 +0530942func (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 +0530943 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000944 allocID uint32, gemPortID uint32, tpID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530945 /* One of the OLT platform (Broadcom BAL) requires that symmetric
946 flows require the same flow_id to be used across UL and DL.
947 Since HSIA flow is the only symmetric flow currently, we need to
948 re-use the flow_id across both direction. The 'flow_category'
949 takes priority over flow_cookie to find any available HSIA_FLOW
950 id for the ONU.
951 */
Shrey Baid26912972020-04-16 21:02:31 +0530952 logger.Infow("adding-hsia-flow",
953 log.Fields{
954 "intf-id": intfID,
955 "onu-id": onuID,
956 "uni-id": uniID,
957 "device-id": f.deviceHandler.device.Id,
958 "classifier": classifier,
959 "action": action,
960 "direction": direction,
961 "alloc-id": allocID,
962 "gemport-id": gemPortID,
963 "logicalflow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530964 var vlanPbit uint32 = 0xff // means no pbit
Gamze Abaka724d0852020-03-18 12:10:24 +0000965 var vlanVid uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400966 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000967 vlanPbit = classifier[VlanPcp].(uint32)
Shrey Baid26912972020-04-16 21:02:31 +0530968 logger.Debugw("found-pbit-in-flow",
969 log.Fields{
970 "vlan-pbit": vlanPbit,
971 "intf-id": intfID,
972 "onu-id": onuID,
973 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800974 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530975 logger.Debugw("pbit-not-found-in-flow",
976 log.Fields{
977 "vlan-pcp": VlanPcp,
978 "intf-id": intfID,
979 "onu-id": onuID,
980 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400981 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000982 if _, ok := classifier[VlanVid]; ok {
983 vlanVid = classifier[VlanVid].(uint32)
Shrey Baid26912972020-04-16 21:02:31 +0530984 log.Debugw("found-vlan-in-the-flow",
985 log.Fields{
986 "vlan-vid": vlanVid,
987 "intf-id": intfID,
988 "onu-id": onuID,
989 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000990 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700991 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530992 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +0530993 logger.Infow("flow-already-exists",
994 log.Fields{
995 "device-id": f.deviceHandler.device.Id,
996 "intf-id": intfID,
997 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800998 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530999 }
Gamze Abaka724d0852020-03-18 12:10:24 +00001000 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +05301001 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301002 return olterrors.NewErrNotFound("hsia-flow-id",
1003 log.Fields{
1004 "direction": direction,
1005 "device-id": f.deviceHandler.device.Id,
1006 "intf-id": intfID,
1007 "onu-id": onuID,
1008 }, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301009 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001010 classifierProto, err := makeOpenOltClassifierField(classifier)
1011 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301012 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301013 }
Shrey Baid26912972020-04-16 21:02:31 +05301014 logger.Debugw("created-classifier-proto",
1015 log.Fields{
1016 "classifier": *classifierProto,
1017 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001018 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001019 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301020 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301021 }
Shrey Baid26912972020-04-16 21:02:31 +05301022 logger.Debugw("created-action-proto",
1023 log.Fields{
1024 "action": *actionProto,
1025 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001026 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301027 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301028 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001029 log.Fields{
1030 "classifier": classifier,
1031 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301032 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001033 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301034 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001035 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
1036 OnuId: int32(onuID),
1037 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +00001038 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +05301039 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001040 AllocId: int32(allocID),
1041 NetworkIntfId: int32(networkIntfID),
1042 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +05301043 Classifier: classifierProto,
1044 Action: actionProto,
1045 Priority: int32(logicalFlow.Priority),
1046 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001047 PortNo: portNo,
1048 TechProfileId: tpID,
1049 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001050 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301051 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301052 }
Shrey Baid26912972020-04-16 21:02:31 +05301053 logger.Infow("hsia-flow-added-to-device-successfully",
1054 log.Fields{"direction": direction,
1055 "device-id": f.deviceHandler.device.Id,
1056 "flow": flow,
1057 "intf-id": intfID,
1058 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001059 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
1060 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1061 flow.OnuId,
1062 flow.UniId,
1063 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301064 return olterrors.NewErrPersistence("update", "flow", flowID,
1065 log.Fields{
1066 "flow": flow,
1067 "device-id": f.deviceHandler.device.Id,
1068 "intf-id": intfID,
1069 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001070 }
1071 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301072}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001073
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001074func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1075 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1076 gemPortID uint32, tpID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301077
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301078 networkIntfID, err := getNniIntfID(classifier, action)
1079 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301080 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001081 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301082 "action": action,
1083 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001084 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301085 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301086
1087 // Clear the action map
1088 for k := range action {
1089 delete(action, k)
1090 }
1091
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001092 action[TrapToHost] = true
1093 classifier[UDPSrc] = uint32(68)
1094 classifier[UDPDst] = uint32(67)
1095 classifier[PacketTagType] = SingleTag
1096 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301097
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001098 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301099 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301100 logger.Infow("flow-exists--not-re-adding",
1101 log.Fields{
1102 "device-id": f.deviceHandler.device.Id,
1103 "intf-id": intfID,
1104 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001105 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301106 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301107
David K. Bainbridge794735f2020-02-11 21:01:37 -08001108 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 +05301109
1110 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301111 return olterrors.NewErrNotFound("flow",
1112 log.Fields{
1113 "interface-id": intfID,
1114 "gem-port": gemPortID,
1115 "cookie": flowStoreCookie,
1116 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001117 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301118 }
1119
Shrey Baid26912972020-04-16 21:02:31 +05301120 logger.Debugw("creating-ul-dhcp-flow",
1121 log.Fields{
1122 "ul_classifier": classifier,
1123 "ul_action": action,
1124 "uplinkFlowId": flowID,
1125 "intf-id": intfID,
1126 "onu-id": onuID,
1127 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301128
David K. Bainbridge794735f2020-02-11 21:01:37 -08001129 classifierProto, err := makeOpenOltClassifierField(classifier)
1130 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301131 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301132 }
Shrey Baid26912972020-04-16 21:02:31 +05301133 logger.Debugw("created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001134 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001135 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301136 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301137 }
1138
David K. Bainbridge794735f2020-02-11 21:01:37 -08001139 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001140 OnuId: int32(onuID),
1141 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301142 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001143 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001144 AllocId: int32(allocID),
1145 NetworkIntfId: int32(networkIntfID),
1146 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301147 Classifier: classifierProto,
1148 Action: actionProto,
1149 Priority: int32(logicalFlow.Priority),
1150 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001151 PortNo: portNo,
1152 TechProfileId: tpID,
1153 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001154 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301155 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001156 }
Shrey Baid26912972020-04-16 21:02:31 +05301157 logger.Infow("dhcp-ul-flow-added-to-device-successfully",
1158 log.Fields{
1159 "device-id": f.deviceHandler.device.Id,
1160 "flow-id": flowID,
1161 "intf-id": intfID,
1162 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001163 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
1164 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
1165 dhcpFlow.OnuId,
1166 dhcpFlow.UniId,
1167 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301168 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1169 log.Fields{
1170 "flow": dhcpFlow,
1171 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301172 }
1173
David K. Bainbridge794735f2020-02-11 21:01:37 -08001174 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301175}
1176
Esin Karamanae41e2b2019-12-17 18:13:13 +00001177//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301178func (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 +00001179 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32) error {
1180 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001181}
1182
1183//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301184func (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 +00001185 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string, tpID uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001186
1187 networkIntfID, err := getNniIntfID(classifier, action)
1188 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301189 return olterrors.NewErrNotFound("nni-interface-id",
1190 log.Fields{
1191 "classifier": classifier,
1192 "action": action,
1193 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001194 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001195 }
1196
1197 // Clear the action map
1198 for k := range action {
1199 delete(action, k)
1200 }
1201
1202 action[TrapToHost] = true
1203 classifier[PacketTagType] = SingleTag
1204 delete(classifier, VlanVid)
1205
1206 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301207 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301208 logger.Infow("flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001209 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001210 }
1211
npujarec5762e2020-01-01 14:08:48 +05301212 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 +00001213
1214 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301215 return olterrors.NewErrNotFound("flow-id",
1216 log.Fields{
1217 "intf-id": intfID,
1218 "oni-id": onuID,
1219 "cookie": flowStoreCookie,
1220 "flow-type": flowType,
1221 "device-id": f.deviceHandler.device.Id,
1222 "onu-id": onuID},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001223 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001224 }
1225
Shrey Baid26912972020-04-16 21:02:31 +05301226 logger.Debugw("creating-upstream-trap-flow",
1227 log.Fields{
1228 "ul_classifier": classifier,
1229 "ul_action": action,
1230 "uplinkFlowId": flowID,
1231 "flowType": flowType,
1232 "device-id": f.deviceHandler.device.Id,
1233 "intf-id": intfID,
1234 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001235
David K. Bainbridge794735f2020-02-11 21:01:37 -08001236 classifierProto, err := makeOpenOltClassifierField(classifier)
1237 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301238 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001239 }
Shrey Baid26912972020-04-16 21:02:31 +05301240 logger.Debugw("created-classifier-proto",
1241 log.Fields{
1242 "classifier": *classifierProto,
1243 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001244 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001245 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301246 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001247 }
1248
David K. Bainbridge794735f2020-02-11 21:01:37 -08001249 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001250 OnuId: int32(onuID),
1251 UniId: int32(uniID),
1252 FlowId: flowID,
1253 FlowType: Upstream,
1254 AllocId: int32(allocID),
1255 NetworkIntfId: int32(networkIntfID),
1256 GemportId: int32(gemPortID),
1257 Classifier: classifierProto,
1258 Action: actionProto,
1259 Priority: int32(logicalFlow.Priority),
1260 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001261 PortNo: portNo,
1262 TechProfileId: tpID,
1263 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001264
David K. Bainbridge794735f2020-02-11 21:01:37 -08001265 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301266 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 -08001267 }
Shrey Baid26912972020-04-16 21:02:31 +05301268 logger.Infof("%s ul-flow-added-to-device-successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001269
David K. Bainbridge794735f2020-02-11 21:01:37 -08001270 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
1271 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1272 flow.OnuId,
1273 flow.UniId,
1274 flow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301275 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 +00001276 }
1277
David K. Bainbridge794735f2020-02-11 21:01:37 -08001278 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001279}
1280
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001281// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001282func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1283 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1284 gemPortID uint32, vlanID uint32, tpID uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05301285 logger.Infow("adding-eapol-to-device",
1286 log.Fields{
1287 "intf-id": intfID,
1288 "onu-id": onuID,
1289 "port-no": portNo,
1290 "alloc-id": allocID,
1291 "gemport-id": gemPortID,
1292 "vlan-id": vlanID,
1293 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301294
1295 uplinkClassifier := make(map[string]interface{})
1296 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301297
manikkaraj kbf256be2019-03-25 00:13:48 +05301298 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001299 uplinkClassifier[EthType] = uint32(EapEthType)
1300 uplinkClassifier[PacketTagType] = SingleTag
1301 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001302 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301303 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001304 uplinkAction[TrapToHost] = true
1305 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301306 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301307 logger.Infow("flow-exists-not-re-adding", log.Fields{
1308 "device-id": f.deviceHandler.device.Id,
1309 "onu-id": onuID,
1310 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001311 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301312 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301313 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +00001314 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +05301315 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301316 return olterrors.NewErrNotFound("flow-id",
1317 log.Fields{
1318 "intf-id": intfID,
1319 "onu-id": onuID,
1320 "coookie": flowStoreCookie,
1321 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001322 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301323 }
Shrey Baid26912972020-04-16 21:02:31 +05301324 logger.Debugw("creating-ul-eapol-flow",
1325 log.Fields{
1326 "ul_classifier": uplinkClassifier,
1327 "ul_action": uplinkAction,
1328 "uplinkFlowId": uplinkFlowID,
1329 "device-id": f.deviceHandler.device.Id,
1330 "intf-id": intfID,
1331 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301332
David K. Bainbridge794735f2020-02-11 21:01:37 -08001333 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1334 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301335 return olterrors.NewErrInvalidValue(log.Fields{
1336 "classifier": uplinkClassifier,
1337 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301338 }
Shrey Baid26912972020-04-16 21:02:31 +05301339 logger.Debugw("created-classifier-proto",
1340 log.Fields{
1341 "classifier": *classifierProto,
1342 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001343 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001344 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301345 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301346 }
Shrey Baid26912972020-04-16 21:02:31 +05301347 logger.Debugw("created-action-proto",
1348 log.Fields{
1349 "action": *actionProto,
1350 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001351 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301352 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301353 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001354 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301355 "action": action,
1356 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001357 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301358 }
1359
David K. Bainbridge794735f2020-02-11 21:01:37 -08001360 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001361 OnuId: int32(onuID),
1362 UniId: int32(uniID),
1363 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001364 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001365 AllocId: int32(allocID),
1366 NetworkIntfId: int32(networkIntfID),
1367 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301368 Classifier: classifierProto,
1369 Action: actionProto,
1370 Priority: int32(logicalFlow.Priority),
1371 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001372 PortNo: portNo,
1373 TechProfileId: tpID,
1374 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001375 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301376 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001377 }
Shrey Baid26912972020-04-16 21:02:31 +05301378 logger.Infow("eapol-ul-flow-added-to-device-successfully",
1379 log.Fields{
1380 "device-id": f.deviceHandler.device.Id,
1381 "onu-id": onuID,
1382 "intf-id": intfID,
1383 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001384 flowCategory := "EAPOL"
1385 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1386 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1387 upstreamFlow.OnuId,
1388 upstreamFlow.UniId,
1389 upstreamFlow.FlowId,
1390 /* lowCategory, */
1391 flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301392 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1393 log.Fields{
1394 "flow": upstreamFlow,
1395 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301396 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001397 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301398}
1399
David K. Bainbridge794735f2020-02-11 21:01:37 -08001400func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001401 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001402
1403 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1404 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1405 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001406 if vlanID != ReservedVlan {
1407 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001408 classifier.OVid = vid
1409 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301410 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001411 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1412 vid := uint32(metadata)
1413 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001414 classifier.IVid = vid
1415 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301416 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301417 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001418 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301419 classifier.OPbits = vlanPcp
1420 } else {
1421 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301422 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001423 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1424 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1425 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1426 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001427 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001428 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1429 classifier.PktTagType = pktTagType
1430
1431 switch pktTagType {
1432 case SingleTag:
1433 case DoubleTag:
1434 case Untagged:
1435 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001436 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301437 }
1438 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001439 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301440}
1441
Gamze Abaka724d0852020-03-18 12:10:24 +00001442func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001443 var actionCmd openoltpb2.ActionCmd
1444 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301445 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001446 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301447 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001448 if _, ok := actionInfo[VlanPcp]; ok {
1449 action.Cmd.RemarkInnerPbits = true
1450 action.IPbits = actionInfo[VlanPcp].(uint32)
1451 if _, ok := actionInfo[VlanVid]; ok {
1452 action.Cmd.TranslateInnerTag = true
1453 action.IVid = actionInfo[VlanVid].(uint32)
1454 }
1455 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001456 } else if _, ok := actionInfo[PushVlan]; ok {
1457 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301458 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001459 if _, ok := actionInfo[VlanPcp]; ok {
1460 action.OPbits = actionInfo[VlanPcp].(uint32)
1461 action.Cmd.RemarkOuterPbits = true
1462 if _, ok := classifierInfo[VlanVid]; ok {
1463 action.IVid = classifierInfo[VlanVid].(uint32)
1464 action.Cmd.TranslateInnerTag = true
1465 }
1466 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001467 } else if _, ok := actionInfo[TrapToHost]; ok {
1468 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301469 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001470 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301471 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001472 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301473}
1474
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001475// getTPpath return the ETCD path for a given UNI port
1476func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uniPath string, TpID uint32) string {
1477 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301478}
1479
Gamze Abakafee36392019-10-03 11:17:24 +00001480// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301481func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1482 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001483 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1484
Gamze Abakafee36392019-10-03 11:17:24 +00001485 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301486 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301487 olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301488 // return err
1489 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001490 }
Shrey Baid26912972020-04-16 21:02:31 +05301491 log.Debugw("tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001492 }
1493 return nil
1494}
1495
1496// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301497func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001498 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001499 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001500 }
npujarec5762e2020-01-01 14:08:48 +05301501 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301502 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1503 log.Fields{
1504 "tp-id": tpID,
1505 "uni-port-name": uniPortName,
1506 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001507 }
1508 return nil
1509}
1510
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001511func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301512 if len(classifier) == 0 { // should never happen
Shrey Baid26912972020-04-16 21:02:31 +05301513 logger.Error("invalid-classfier-object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301514 return 0
1515 }
Shrey Baid26912972020-04-16 21:02:31 +05301516 logger.Debugw("generating-flow-store-cookie",
1517 log.Fields{
1518 "classifier": classifier,
1519 "gemport-id": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301520 var jsonData []byte
1521 var flowString string
1522 var err error
1523 // TODO: Do we need to marshall ??
1524 if jsonData, err = json.Marshal(classifier); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301525 logger.Error("failed-to-encode-classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301526 return 0
1527 }
1528 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001529 if gemPortID != 0 {
1530 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301531 }
1532 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001533 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301534 hash := big.NewInt(0)
1535 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301536 generatedHash := hash.Uint64()
Shrey Baid26912972020-04-16 21:02:31 +05301537 logger.Debugw("hash-generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301538 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301539}
1540
npujarec5762e2020-01-01 14:08:48 +05301541func (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 +05301542 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001543 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001544 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1545 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1546 */
1547 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001548 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001549 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001550 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001551 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001552 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301553 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001554 if existingFlows != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301555 logger.Debugw("flow-exists-for-given-flowID--appending-it-to-current-flow",
1556 log.Fields{
1557 "flow-id": flow.FlowId,
1558 "device-id": f.deviceHandler.device.Id,
1559 "intf-id": intfID,
1560 "onu-id": flow.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001561 //for _, f := range *existingFlows {
1562 // flows = append(flows, f)
1563 //}
1564 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001565 }
Shrey Baid26912972020-04-16 21:02:31 +05301566 logger.Debugw("updated-flows-for-given-flowID-and-onuid",
1567 log.Fields{
1568 "updatedflow": flows,
1569 "flow-id": flow.FlowId,
1570 "onu-id": flow.OnuId,
1571 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +05301572 return &flows
1573}
1574
npujarec5762e2020-01-01 14:08:48 +05301575func (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 +05301576 logger.Debugw("storing-flow(s)-into-kv-store", log.Fields{
1577 "flow-id": flowID,
1578 "device-id": f.deviceHandler.device.Id,
1579 "intf-id": intfID,
1580 "onu-id": onuID})
npujarec5762e2020-01-01 14:08:48 +05301581 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301582 logger.Warnw("error-while-storing-flow-into-kv-store", log.Fields{
1583 "device-id": f.deviceHandler.device.Id,
1584 "onu-id": onuID,
1585 "intf-id": intfID,
1586 "flow-id": flowID})
manikkaraj k17652a72019-05-06 09:06:36 -04001587 return err
1588 }
Shrey Baid26912972020-04-16 21:02:31 +05301589 logger.Infow("stored-flow(s)-into-kv-store-successfully!", log.Fields{
1590 "device-id": f.deviceHandler.device.Id,
1591 "onu-id": onuID,
1592 "intf-id": intfID,
1593 "flow-id": flowID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301594 return nil
1595}
1596
David K. Bainbridge794735f2020-02-11 21:01:37 -08001597func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001598
1599 var intfID uint32
1600 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1601 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1602 */
1603 if deviceFlow.AccessIntfId != -1 {
1604 intfID = uint32(deviceFlow.AccessIntfId)
1605 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001606 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001607 intfID = uint32(deviceFlow.NetworkIntfId)
1608 }
1609
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001610 logger.Debugw("sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301611 "flow": *deviceFlow,
1612 "device-id": f.deviceHandler.device.Id,
1613 "intf-id": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301614 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001615
1616 st, _ := status.FromError(err)
1617 if st.Code() == codes.AlreadyExists {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001618 logger.Debug("flow-already-exists", log.Fields{
1619 "err": err,
1620 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301621 "device-id": f.deviceHandler.device.Id,
1622 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001623 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301624 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001625
1626 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301627 logger.Errorw("failed-to-add-flow-to-device",
1628 log.Fields{"err": err,
1629 "device-flow": deviceFlow,
1630 "device-id": f.deviceHandler.device.Id,
1631 "intf-id": intfID})
npujarec5762e2020-01-01 14:08:48 +05301632 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001633 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001634 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301635 if deviceFlow.GemportId != -1 {
1636 // No need to register the flow if it is a trap on nni flow.
npujarec5762e2020-01-01 14:08:48 +05301637 f.registerFlow(ctx, logicalFlow, deviceFlow)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301638 }
Shrey Baid26912972020-04-16 21:02:31 +05301639 logger.Infow("flow-added-to-device-successfully ",
1640 log.Fields{
1641 "flow": *deviceFlow,
1642 "device-id": f.deviceHandler.device.Id,
1643 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001644 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001645}
1646
Matteo Scandolo92186242020-06-12 10:54:18 -07001647func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
Shrey Baid26912972020-04-16 21:02:31 +05301648 logger.Debugw("sending-flow-to-device-via-grpc",
1649 log.Fields{
1650 "flow": *deviceFlow,
1651 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001652 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1653 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001654 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Shrey Baid26912972020-04-16 21:02:31 +05301655 logger.Warnw("can-not-remove-flow-from-device--unreachable",
1656 log.Fields{
1657 "err": err,
1658 "deviceFlow": deviceFlow,
1659 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001660 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001661 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001662 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001663 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001664
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001665 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001666 logger.Infow("flow-removed-from-device-successfully", log.Fields{
1667 "of-flow-id": ofFlowID,
1668 "flow": *deviceFlow,
1669 "device-id": f.deviceHandler.device.Id,
1670 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001671 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301672}
1673
David K. Bainbridge794735f2020-02-11 21:01:37 -08001674func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001675
1676 classifierInfo := make(map[string]interface{})
1677 actionInfo := make(map[string]interface{})
1678
1679 classifierInfo[EthType] = uint32(LldpEthType)
1680 classifierInfo[PacketTagType] = Untagged
1681 actionInfo[TrapToHost] = true
1682
1683 // LLDP flow is installed to trap LLDP packets on the NNI port.
1684 // We manage flow_id resource pool on per PON port basis.
1685 // Since this situation is tricky, as a hack, we pass the NNI port
1686 // index (network_intf_id) as PON port Index for the flow_id resource
1687 // pool. Also, there is no ONU Id available for trapping LLDP packets
1688 // on NNI port, use onu_id as -1 (invalid)
1689 // ****************** CAVEAT *******************
1690 // This logic works if the NNI Port Id falls within the same valid
1691 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1692 // we need to have a re-look at this.
1693 // *********************************************
1694
1695 var onuID = -1
1696 var uniID = -1
1697 var gemPortID = -1
1698
David K. Bainbridge794735f2020-02-11 21:01:37 -08001699 networkInterfaceID, err := IntfIDFromNniPortNum(portNo)
1700 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301701 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001702 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001703 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301704 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301705 logger.Infow("flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001706 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001707 }
npujarec5762e2020-01-01 14:08:48 +05301708 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001709
1710 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301711 return olterrors.NewErrNotFound("flow-id",
1712 log.Fields{
1713 "interface-id": networkInterfaceID,
1714 "onu-id": onuID,
1715 "uni-id": uniID,
1716 "gem-port-id": gemPortID,
1717 "cookie": flowStoreCookie,
1718 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001719 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001720 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001721 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1722 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301723 return olterrors.NewErrInvalidValue(
1724 log.Fields{
1725 "classifier": classifierInfo,
1726 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001727 }
Shrey Baid26912972020-04-16 21:02:31 +05301728 logger.Debugw("created-classifier-proto",
1729 log.Fields{
1730 "classifier": *classifierProto,
1731 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001732 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001733 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301734 return olterrors.NewErrInvalidValue(
1735 log.Fields{
1736 "action": actionInfo,
1737 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001738 }
Shrey Baid26912972020-04-16 21:02:31 +05301739 logger.Debugw("created-action-proto",
1740 log.Fields{
1741 "action": *actionProto,
1742 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001743
1744 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1745 OnuId: int32(onuID), // OnuId not required
1746 UniId: int32(uniID), // UniId not used
1747 FlowId: flowID,
1748 FlowType: Downstream,
1749 NetworkIntfId: int32(networkInterfaceID),
1750 GemportId: int32(gemPortID),
1751 Classifier: classifierProto,
1752 Action: actionProto,
1753 Priority: int32(flow.Priority),
1754 Cookie: flow.Cookie,
1755 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001756 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301757 return olterrors.NewErrFlowOp("add", flowID,
1758 log.Fields{
1759 "flow": downstreamflow,
1760 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001761 }
Shrey Baid26912972020-04-16 21:02:31 +05301762 logger.Infow("lldp-trap-on-nni-flow-added-to-device-successfully",
1763 log.Fields{
1764 "device-id": f.deviceHandler.device.Id,
1765 "onu-id": onuID,
1766 "flow-id": flowID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001767 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1768 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1769 int32(onuID),
1770 int32(uniID),
1771 flowID, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301772 return olterrors.NewErrPersistence("update", "flow", flowID,
1773 log.Fields{
1774 "flow": downstreamflow,
1775 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001776 }
1777 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301778}
1779
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001780func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1781 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001782}
1783
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001784//getOnuDevice to fetch onu from cache or core.
1785func (f *OpenOltFlowMgr) getOnuDevice(intfID uint32, onuID uint32) (*OnuDevice, error) {
1786 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1787 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1788 if !ok {
Shrey Baid26912972020-04-16 21:02:31 +05301789 logger.Debugw("couldnt-find-onu-in-cache",
1790 log.Fields{
1791 "intf-id": intfID,
1792 "onu-id": onuID,
1793 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001794 onuDevice, err := f.getChildDevice(intfID, onuID)
1795 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301796 return nil, olterrors.NewErrNotFound("onu-child-device",
1797 log.Fields{
1798 "onu-id": onuID,
1799 "intf-id": intfID,
1800 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001801 }
1802 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1803 //better to ad the device to cache here.
1804 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1805 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301806 logger.Debugw("found-onu-in-cache",
1807 log.Fields{
1808 "intf-id": intfID,
1809 "onu-id": onuID,
1810 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001811 }
1812
1813 return onuDev.(*OnuDevice), nil
1814}
1815
1816//getChildDevice to fetch onu
1817func (f *OpenOltFlowMgr) getChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
Shrey Baid26912972020-04-16 21:02:31 +05301818 logger.Infow("GetChildDevice",
1819 log.Fields{
1820 "pon-port": intfID,
1821 "onu-id": onuID,
1822 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001823 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001824 onuDevice, err := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
1825 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301826 return nil, olterrors.NewErrNotFound("onu",
1827 log.Fields{
1828 "interface-id": parentPortNo,
1829 "onu-id": onuID,
1830 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001831 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301832 }
Shrey Baid26912972020-04-16 21:02:31 +05301833 logger.Infow("successfully-received-child-device-from-core",
1834 log.Fields{
1835 "device-id": f.deviceHandler.device.Id,
1836 "child_device_id": onuDevice.Id,
1837 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301838 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301839}
1840
1841func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Shrey Baid26912972020-04-16 21:02:31 +05301842 logger.Info("unimplemented-flow %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301843 return nil
1844}
1845
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001846func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
Shrey Baid26912972020-04-16 21:02:31 +05301847 logger.Info("unimplemented-device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301848}
1849
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001850func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001851 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001852 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001853 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001854 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001855}
1856
Girish Gowdra6b130582019-11-20 16:45:20 +05301857func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001858 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301859 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301860 logger.Debugw("couldnt-find-onu-child-device",
1861 log.Fields{
1862 "intf-id": intfID,
1863 "onu-id": onuID,
1864 "uni-id": uniID,
1865 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001866 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301867 }
1868
1869 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Shrey Baid26912972020-04-16 21:02:31 +05301870 logger.Debugw("sending-gem-port-delete-to-openonu-adapter",
1871 log.Fields{
1872 "msg": *delGemPortMsg,
1873 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301874 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1875 delGemPortMsg,
1876 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301877 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001878 onuDev.deviceType,
1879 onuDev.deviceID,
1880 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301881 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1882 log.Fields{
1883 "from-adapter": f.deviceHandler.device.Type,
1884 "to-adapter": onuDev.deviceType,
1885 "onu-id": onuDev.deviceID,
1886 "proxyDeviceID": onuDev.proxyDeviceID,
1887 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301888 }
Shrey Baid26912972020-04-16 21:02:31 +05301889 logger.Infow("success-sending-del-gem-port-to-onu-adapter",
1890 log.Fields{
1891 "msg": delGemPortMsg,
1892 "from-adapter": f.deviceHandler.device.Type,
1893 "to-adapter": onuDev.deviceType,
1894 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301895 return nil
1896}
1897
1898func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001899 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301900 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301901 logger.Warnw("couldnt-find-onu-child-device",
1902 log.Fields{
1903 "intf-id": intfID,
1904 "onu-id": onuID,
1905 "uni-id": uniID,
1906 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001907 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301908 }
1909
1910 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Shrey Baid26912972020-04-16 21:02:31 +05301911 logger.Debugw("sending-tcont-delete-to-openonu-adapter",
1912 log.Fields{
1913 "msg": *delTcontMsg,
1914 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301915 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1916 delTcontMsg,
1917 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301918 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001919 onuDev.deviceType,
1920 onuDev.deviceID,
1921 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301922 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1923 log.Fields{
1924 "from-adapter": f.deviceHandler.device.Type,
1925 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1926 "proxyDeviceID": onuDev.proxyDeviceID,
1927 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301928 }
Shrey Baid26912972020-04-16 21:02:31 +05301929 logger.Infow("success-sending-del-tcont-to-onu-adapter",
1930 log.Fields{
1931 "msg": delTcontMsg,
1932 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301933 return nil
1934}
1935
Girish Gowdra3d633032019-12-10 16:37:05 +05301936func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1937 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1938 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1939 if val.(int) > 0 {
1940 pnFlDels := val.(int) - 1
1941 if pnFlDels > 0 {
Shrey Baid26912972020-04-16 21:02:31 +05301942 logger.Debugw("flow-delete-succeeded--more-pending",
1943 log.Fields{
1944 "intf": Intf,
1945 "onu-id": onuID,
1946 "uni-id": uniID,
1947 "currpendingflowcnt": pnFlDels,
1948 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301949 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1950 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301951 logger.Debugw("all-pending-flow-deletes-handled--removing-entry-from-map",
1952 log.Fields{
1953 "intf": Intf,
1954 "onu-id": onuID,
1955 "uni-id": uniID,
1956 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301957 f.pendingFlowDelete.Delete(pnFlDelKey)
1958 }
1959 }
1960 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301961 logger.Debugw("no-pending-delete-flows-found",
1962 log.Fields{
1963 "intf": Intf,
1964 "onu-id": onuID,
1965 "uni-id": uniID,
1966 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301967
1968 }
1969
1970}
1971
Girish Gowdrac3037402020-01-22 20:29:53 +05301972// Once the gemport is released for a given onu, it also has to be cleared from local cache
1973// which was used for deriving the gemport->logicalPortNo during packet-in.
1974// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1975// is conveyed to ONOS during packet-in OF message.
1976func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001977
Matteo Scandolo60913ed2020-06-23 19:31:14 -07001978 f.onuGemInfoLock.Lock()
1979 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001980
Shrey Baid26912972020-04-16 21:02:31 +05301981 logger.Infow("deleting-gem-from-local-cache",
1982 log.Fields{
Matteo Scandolo60913ed2020-06-23 19:31:14 -07001983 "gem-port-id": gemPortID,
1984 "intf-id": intfID,
1985 "onu-id": onuID,
1986 "device-id": f.deviceHandler.device.Id,
1987 "onu-gem": f.onuGemInfo[intfID]})
Girish Gowdrac3037402020-01-22 20:29:53 +05301988 onugem := f.onuGemInfo[intfID]
Matteo Scandolo60913ed2020-06-23 19:31:14 -07001989deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001990 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301991 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001992 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301993 // If the gemport is found, delete it from local cache.
1994 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001995 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1996 onugem[i] = onu
Shrey Baid26912972020-04-16 21:02:31 +05301997 logger.Infow("removed-gemport-from-local-cache",
1998 log.Fields{
1999 "intf-id": intfID,
2000 "onu-id": onuID,
2001 "deletedgemport-id": gemPortID,
2002 "gemports": onu.GemPorts,
2003 "device-id": f.deviceHandler.device.Id})
Matteo Scandolo60913ed2020-06-23 19:31:14 -07002004 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05302005 }
2006 }
Matteo Scandolo60913ed2020-06-23 19:31:14 -07002007 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05302008 }
2009 }
2010}
2011
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302012//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002013// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302014func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302015 gemPortID int32, flowID uint32, flowDirection string,
2016 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002017
Chaitrashree G S90a17952019-11-14 21:51:21 -05002018 tpID, err := getTpIDFromFlow(flow)
2019 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302020 return olterrors.NewErrNotFound("tp-id",
2021 log.Fields{
2022 "flow": flow,
2023 "intf": Intf,
2024 "onu-id": onuID,
2025 "uni-id": uniID,
2026 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002027 }
Gamze Abakafee36392019-10-03 11:17:24 +00002028
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002029 if len(updatedFlows) >= 0 {
2030 // There are still flows referencing the same flow_id.
2031 // So the flow should not be freed yet.
2032 // For ex: Case of HSIA where same flow is shared
2033 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00002034 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302035 olterrors.NewErrPersistence("update", "flow", flowID,
2036 log.Fields{
2037 "flow": updatedFlows,
2038 "device-id": f.deviceHandler.device.Id}, err).Log()
Girish Kumarf26e4882020-03-05 06:49:10 +00002039 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002040 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05302041 // Do this for subscriber flows only (not trap from NNI flows)
2042 if onuID != -1 && uniID != -1 {
2043 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
2044 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Shrey Baid26912972020-04-16 21:02:31 +05302045 logger.Debugw("creating-entry-for-pending-flow-delete",
2046 log.Fields{
2047 "flow-id": flowID,
2048 "intf": Intf,
2049 "onu-id": onuID,
2050 "uni-id": uniID,
2051 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302052 f.pendingFlowDelete.Store(pnFlDelKey, 1)
2053 } else {
2054 pnFlDels := val.(int) + 1
Shrey Baid26912972020-04-16 21:02:31 +05302055 logger.Debugw("updating-flow-delete-entry",
2056 log.Fields{
2057 "flow-id": flowID,
2058 "intf": Intf,
2059 "onu-id": onuID,
2060 "uni-id": uniID,
2061 "currPendingFlowCnt": pnFlDels,
2062 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302063 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
2064 }
2065
2066 defer f.deletePendingFlows(Intf, onuID, uniID)
2067 }
2068
Shrey Baid26912972020-04-16 21:02:31 +05302069 logger.Debugw("releasing-flow-id-to-resource-manager",
2070 log.Fields{
2071 "Intf": Intf,
2072 "onu-id": onuID,
2073 "uni-id": uniID,
2074 "flow-id": flowID,
2075 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302076 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002077
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002078 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302079 tpPath := f.getTPpath(Intf, uni, tpID)
Shrey Baid26912972020-04-16 21:02:31 +05302080 logger.Debugw("getting-techprofile-instance-for-subscriber",
2081 log.Fields{
2082 "TP-PATH": tpPath,
2083 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302084 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00002085 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +05302086 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
2087 log.Fields{
2088 "tp-id": tpID,
2089 "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002090 }
2091
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302092 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Matteo Scandoloac032b12020-08-03 11:14:22 -07002093 used, err := f.isGemPortUsedByAnotherFlow(gemPK)
2094 if err != nil {
2095 return err
2096 }
2097 if used {
2098 if f.perGemPortLock.TryLock(gemPK) {
2099 flowIDs := f.flowsUsedByGemPort[gemPK]
2100 for i, flowIDinMap := range flowIDs {
2101 if flowIDinMap == flowID {
2102 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
2103 // everytime flowsUsedByGemPort cache is updated the same should be updated
2104 // in kv store by calling UpdateFlowIDsForGem
2105 f.flowsUsedByGemPort[gemPK] = flowIDs
2106 f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs)
2107 break
2108 }
Gamze Abakafee36392019-10-03 11:17:24 +00002109 }
Matteo Scandoloac032b12020-08-03 11:14:22 -07002110 logger.Debugw("gem-port-id-is-still-used-by-other-flows",
2111 log.Fields{
2112 "gemport-id": gemPortID,
2113 "usedByFlows": flowIDs,
2114 "device-id": f.deviceHandler.device.Id})
2115 f.perGemPortLock.Unlock(gemPK)
2116 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00002117 }
Matteo Scandoloac032b12020-08-03 11:14:22 -07002118 logger.Error("failed-to-acquire-per-gem-port-lock",
Shrey Baid26912972020-04-16 21:02:31 +05302119 log.Fields{
Matteo Scandoloac032b12020-08-03 11:14:22 -07002120 "gemport-id": gemPortID,
2121 "device-id": f.deviceHandler.device.Id,
2122 "key": gemPK,
2123 })
2124 return olterrors.NewErrAdapter("failed-to-acquire-per-gem-port-lock", log.Fields{
2125 "gemport-id": gemPortID,
2126 "device-id": f.deviceHandler.device.Id,
2127 "key": gemPK,
2128 }, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00002129 }
Shrey Baid26912972020-04-16 21:02:31 +05302130 logger.Debugf("gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05302131 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002132 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
2133 // 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 +05302134 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Girish Gowdrac3037402020-01-22 20:29:53 +05302135 f.deleteGemPortFromLocalCache(Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002136 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302137 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
2138 // by calling DeleteFlowIDsForGem
Matteo Scandoloac032b12020-08-03 11:14:22 -07002139 if f.perGemPortLock.TryLock(gemPK) {
2140 delete(f.flowsUsedByGemPort, gemPK)
2141 f.perGemPortLock.Unlock(gemPK)
2142 } else {
2143 logger.Error("failed-to-acquire-per-gem-port-lock",
2144 log.Fields{
2145 "device-id": f.deviceHandler.device.Id,
2146 "key": gemPK,
2147 })
2148 }
npujarec5762e2020-01-01 14:08:48 +05302149 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
2150 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002151 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05302152 // Delete the gem port on the ONU.
2153 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302154 logger.Errorw("error-processing-delete-gem-port-towards-onu",
2155 log.Fields{
2156 "err": err,
2157 "intf": Intf,
2158 "onu-id": onuID,
2159 "uni-id": uniID,
2160 "device-id": f.deviceHandler.device.Id,
2161 "gemport-id": gemPortID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302162 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002163 switch techprofileInst := techprofileInst.(type) {
2164 case *tp.TechProfile:
2165 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
2166 if !ok {
2167 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
2168 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
2169 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
2170 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
2171 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
2172 // Delete the TCONT on the ONU.
2173 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
2174 logger.Errorw("error-processing-delete-tcont-towards-onu",
2175 log.Fields{
2176 "intf": Intf,
2177 "onu-id": onuID,
2178 "uni-id": uniID,
2179 "device-id": f.deviceHandler.device.Id,
2180 "alloc-id": techprofileInst.UsScheduler.AllocID})
2181 }
2182 }
2183 case *tp.EponProfile:
npujarec5762e2020-01-01 14:08:48 +05302184 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
npujarec5762e2020-01-01 14:08:48 +05302185 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002186 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302187 // Delete the TCONT on the ONU.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002188 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.AllocID), tpPath); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302189 logger.Errorw("error-processing-delete-tcont-towards-onu",
2190 log.Fields{
2191 "intf": Intf,
2192 "onu-id": onuID,
2193 "uni-id": uniID,
2194 "device-id": f.deviceHandler.device.Id,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002195 "alloc-id": techprofileInst.AllocID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302196 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002197 default:
2198 logger.Errorw("error-unknown-tech",
2199 log.Fields{
2200 "techprofileInst": techprofileInst})
Gamze Abakafee36392019-10-03 11:17:24 +00002201 }
2202 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002203 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302204 return nil
2205}
2206
David K. Bainbridge794735f2020-02-11 21:01:37 -08002207// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302208func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302209
Shrey Baid26912972020-04-16 21:02:31 +05302210 logger.Infow("clear-flow-from-resource-manager",
2211 log.Fields{
2212 "flowDirection": flowDirection,
2213 "flow": *flow,
2214 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002215
2216 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05302217 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002218 return
2219 }
2220
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302221 var updatedFlows []rsrcMgr.FlowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302222 classifierInfo := make(map[string]interface{})
2223
2224 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
2225 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002226 logger.Error(err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302227 return
2228 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302229
David K. Bainbridge794735f2020-02-11 21:01:37 -08002230 onuID := int32(onu)
2231 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302232
2233 for _, field := range flows.GetOfbFields(flow) {
2234 if field.Type == flows.IP_PROTO {
2235 classifierInfo[IPProto] = field.GetIpProto()
Shrey Baid26912972020-04-16 21:02:31 +05302236 logger.Debugw("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302237 }
2238 }
Shrey Baid26912972020-04-16 21:02:31 +05302239 logger.Infow("extracted-access-info-from-flow-to-be-deleted",
2240 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002241 "flow-id": flow.Id,
2242 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302243 "onu-id": onuID,
2244 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302245
2246 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2247 onuID = -1
2248 uniID = -1
Shrey Baid26912972020-04-16 21:02:31 +05302249 logger.Debug("trap-on-nni-flow-set-oni--uni-to- -1")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002250 Intf, err = IntfIDFromNniPortNum(inPort)
2251 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002252 logger.Errorw("invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002253 log.Fields{
2254 "port-number": inPort,
2255 "error": err})
2256 return
2257 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302258 }
npujarec5762e2020-01-01 14:08:48 +05302259 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002260 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302261 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302262 if flowInfo == nil {
Shrey Baid26912972020-04-16 21:02:31 +05302263 logger.Debugw("no-flowinfo-found-in-kv-store",
2264 log.Fields{
2265 "intf": Intf,
2266 "onu-id": onuID,
2267 "uni-id": uniID,
2268 "flow-id": flowID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302269 return
2270 }
2271 updatedFlows = nil
2272 for _, flow := range *flowInfo {
2273 updatedFlows = append(updatedFlows, flow)
2274 }
2275
2276 for i, storedFlow := range updatedFlows {
2277 if flow.Id == storedFlow.LogicalFlowID {
2278 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Shrey Baid26912972020-04-16 21:02:31 +05302279 logger.Debugw("flow-to-be-deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002280 // DKB
Matteo Scandolo92186242020-06-12 10:54:18 -07002281 if err = f.removeFlowFromDevice(&removeFlowMessage, flow.Id); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002282 logger.Errorw("failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002283 return
2284 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002285 logger.Info("flow-removed-from-device-successfully", log.Fields{
2286 "flow-id": flow.Id,
2287 "stored-flow": storedFlow,
2288 "device-id": f.deviceHandler.device.Id,
2289 "stored-flow-id": flowID,
2290 "onu-id": onuID,
2291 "intf": Intf,
2292 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08002293 //Remove the Flow from FlowInfo
2294 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
2295 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
2296 flowID, flowDirection, portNum, updatedFlows); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07002297 logger.Error("failed-to-clear-resources-for-flow", log.Fields{
2298 "flow-id": flow.Id,
2299 "stored-flow": storedFlow,
2300 "device-id": f.deviceHandler.device.Id,
2301 "stored-flow-id": flowID,
2302 "onu-id": onuID,
2303 "intf": Intf,
2304 })
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302305 return
2306 }
2307 }
2308 }
2309 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002310}
2311
Esin Karamanccb714b2019-11-29 15:02:06 +00002312//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
2313// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05302314func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002315 classifierInfo := make(map[string]interface{})
2316 formulateClassifierInfoFromFlow(classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00002317 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002318
2319 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302320 logger.Warnw("no-inport-found--cannot-release-resources-of-the-multicast-flow", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002321 return
2322 }
2323
Esin Karamanccb714b2019-11-29 15:02:06 +00002324 var onuID = int32(NoneOnuID)
2325 var uniID = int32(NoneUniID)
2326 var flowID uint32
2327 var updatedFlows []rsrcMgr.FlowInfo
2328
npujarec5762e2020-01-01 14:08:48 +05302329 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002330
2331 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302332 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002333 if flowInfo == nil {
Shrey Baid26912972020-04-16 21:02:31 +05302334 logger.Debugw("no-multicast-flowinfo-found-in-the-kv-store",
2335 log.Fields{
2336 "intf": networkInterfaceID,
2337 "onu-id": onuID,
2338 "uni-id": uniID,
2339 "flow-id": flowID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002340 continue
2341 }
2342 updatedFlows = nil
2343 for _, flow := range *flowInfo {
2344 updatedFlows = append(updatedFlows, flow)
2345 }
2346 for i, storedFlow := range updatedFlows {
2347 if flow.Id == storedFlow.LogicalFlowID {
2348 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Shrey Baid26912972020-04-16 21:02:31 +05302349 logger.Debugw("multicast-flow-to-be-deleted",
2350 log.Fields{
2351 "flow": storedFlow,
2352 "flow-id": flow.Id,
2353 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002354 //remove from device
Matteo Scandolo92186242020-06-12 10:54:18 -07002355 if err := f.removeFlowFromDevice(&removeFlowMessage, flow.Id); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002356 // DKB
Girish Kumar2ad402b2020-03-20 19:45:12 +00002357 logger.Errorw("failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002358 log.Fields{
2359 "flow-id": flow.Id,
2360 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002361 return
2362 }
Shrey Baid26912972020-04-16 21:02:31 +05302363 logger.Infow("multicast-flow-removed-from-device-successfully", log.Fields{"flow-id": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002364 //Remove the Flow from FlowInfo
2365 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05302366 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302367 logger.Errorw("failed-to-delete-multicast-flow-from-the-kv-store",
2368 log.Fields{"flow": storedFlow,
2369 "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002370 return
2371 }
2372 //release flow id
Shrey Baid26912972020-04-16 21:02:31 +05302373 logger.Debugw("releasing-multicast-flow-id",
2374 log.Fields{"flow-id": flowID,
2375 "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05302376 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002377 }
2378 }
2379 }
2380}
2381
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002382//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002383func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002384 logger.Infow("removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302385 var direction string
2386 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002387
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302388 for _, action := range flows.GetActions(flow) {
2389 if action.Type == flows.OUTPUT {
2390 if out := action.GetOutput(); out != nil {
2391 actionInfo[Output] = out.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002392 logger.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302393 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302394 logger.Error("invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002395 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002396 }
2397 }
2398 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002399
2400 if flows.HasGroup(flow) {
2401 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07002402 f.clearFlowFromResourceManager(ctx, flow, direction)
2403 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002404 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302405 direction = Upstream
2406 } else {
2407 direction = Downstream
2408 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302409
Girish Gowdracefae192020-03-19 18:14:10 -07002410 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(flow, direction)
2411 if err != nil {
2412 return err
2413 }
2414
2415 userKey := tpLockKey{intfID, onuID, uniID}
2416
2417 // Serialize flow removes on a per subscriber basis
2418 if f.perUserFlowHandleLock.TryLock(userKey) {
2419 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
2420 f.perUserFlowHandleLock.Unlock(userKey)
2421 } else {
2422 // Ideally this should never happen
Shrey Baid26912972020-04-16 21:02:31 +05302423 logger.Errorw("failed-to-acquire-lock-to-remove-flow--remove-aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07002424 return errors.New("failed-to-acquire-per-user-lock")
2425 }
2426
2427 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002428}
2429
Girish Gowdra3d633032019-12-10 16:37:05 +05302430func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
2431 uniID uint32, ch chan bool) {
2432 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2433 for {
2434 select {
2435 case <-time.After(20 * time.Millisecond):
2436 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Shrey Baid26912972020-04-16 21:02:31 +05302437 logger.Debug("pending-flow-deletes-completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05302438 ch <- true
2439 return
2440 }
2441 case <-ctx.Done():
Shrey Baid26912972020-04-16 21:02:31 +05302442 logger.Error("flow-delete-wait-handler-routine-canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05302443 return
2444 }
2445 }
2446}
2447
Esin Karamanae41e2b2019-12-17 18:13:13 +00002448//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2449func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2450 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2451 if ethType, ok := classifierInfo[EthType]; ok {
2452 if ethType.(uint32) == IPv4EthType {
2453 if ipProto, ok := classifierInfo[IPProto]; ok {
2454 if ipProto.(uint32) == IgmpProto {
2455 return true
2456 }
2457 }
2458 }
2459 }
2460 }
2461 return false
2462}
2463
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002464// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302465// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002466func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002467 classifierInfo := make(map[string]interface{})
2468 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002469 var UsMeterID uint32
2470 var DsMeterID uint32
2471
Shrey Baid26912972020-04-16 21:02:31 +05302472 logger.Infow("adding-flow",
2473 log.Fields{
2474 "flow": flow,
2475 "flowmetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002476 formulateClassifierInfoFromFlow(classifierInfo, flow)
2477
2478 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
2479 if err != nil {
2480 // Error logging is already done in the called function
2481 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002482 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302483 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002484
Esin Karamanccb714b2019-11-29 15:02:06 +00002485 if flows.HasGroup(flow) {
2486 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002487 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002488 }
2489
manikkaraj k17652a72019-05-06 09:06:36 -04002490 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00002491 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
2492 if err != nil {
2493 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002494 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002495 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002496
Shrey Baid26912972020-04-16 21:02:31 +05302497 logger.Debugw("flow-ports",
2498 log.Fields{
2499 "classifierinfo_inport": classifierInfo[InPort],
2500 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002501 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002502
Humera Kouser94d7a842019-08-25 19:04:32 -04002503 if ethType, ok := classifierInfo[EthType]; ok {
2504 if ethType.(uint32) == LldpEthType {
Shrey Baid26912972020-04-16 21:02:31 +05302505 logger.Info("adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002506 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002507 }
2508 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002509 if ipProto, ok := classifierInfo[IPProto]; ok {
2510 if ipProto.(uint32) == IPProtoDhcp {
2511 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302512 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002513 logger.Debug("trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002514 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002515 }
2516 }
2517 }
2518 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002519 if isIgmpTrapDownstreamFlow(classifierInfo) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002520 logger.Debug("trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002521 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002522 }
A R Karthick1f85b802019-10-11 05:06:05 +00002523
npujarec5762e2020-01-01 14:08:48 +05302524 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002525
Chaitrashree G S90a17952019-11-14 21:51:21 -05002526 TpID, err := getTpIDFromFlow(flow)
2527 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302528 return olterrors.NewErrNotFound("tpid-for-flow",
2529 log.Fields{
2530 "flow": flow,
2531 "intf-id": IntfID,
2532 "onu-id": onuID,
2533 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002534 }
Shrey Baid26912972020-04-16 21:02:31 +05302535 logger.Debugw("tpid-for-this-subcriber",
2536 log.Fields{
2537 "tp-id": TpID,
2538 "intf-id": intfID,
2539 "onu-id": onuID,
2540 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002541 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002542 UsMeterID = flows.GetMeterIdFromFlow(flow)
Shrey Baid26912972020-04-16 21:02:31 +05302543 logger.Debugw("upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002544 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002545 DsMeterID = flows.GetMeterIdFromFlow(flow)
Shrey Baid26912972020-04-16 21:02:31 +05302546 logger.Debugw("downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002547
2548 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302549
2550 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2551 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Shrey Baid26912972020-04-16 21:02:31 +05302552 logger.Debugw("no-pending-flows-found--going-ahead-with-flow-install",
2553 log.Fields{
2554 "intf-id": intfID,
2555 "onu-id": onuID,
2556 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302557 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302558 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05302559 pendingFlowDelComplete := make(chan bool)
2560 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
2561 select {
2562 case <-pendingFlowDelComplete:
Shrey Baid26912972020-04-16 21:02:31 +05302563 logger.Debugw("all-pending-flow-deletes-completed",
2564 log.Fields{
2565 "intf-id": intfID,
2566 "onu-id": onuID,
2567 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302568 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302569
2570 case <-time.After(10 * time.Second):
Shrey Baid26912972020-04-16 21:02:31 +05302571 return olterrors.NewErrTimeout("pending-flow-deletes",
2572 log.Fields{
2573 "intf-id": intfID,
2574 "onu-id": onuID,
2575 "uni-id": uniID}, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +05302576 }
2577 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002578 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002579}
2580
Esin Karamanccb714b2019-11-29 15:02:06 +00002581// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002582func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002583 classifierInfo[PacketTagType] = DoubleTag
Shrey Baid26912972020-04-16 21:02:31 +05302584 logger.Debugw("add-multicast-flow", log.Fields{
2585 "classifier-info": classifierInfo,
2586 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002587
Esin Karaman65409d82020-03-18 10:58:18 +00002588 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002589 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002590 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002591 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002592 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
2593 //otherwise, classification is based on ipv4_dst by default.
2594 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
2595 mcastFlowClassificationByEthDst := false
2596
2597 if mcastFlowClassificationByEthDst {
2598 //replace ipDst with ethDst
2599 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
2600 flows.IsMulticastIp(ipv4Dst.(uint32)) {
2601 // replace ipv4_dst classifier with eth_dst
2602 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
2603 delete(classifierInfo, Ipv4Dst)
2604 classifierInfo[EthDst] = multicastMac
Shrey Baid26912972020-04-16 21:02:31 +05302605 logger.Debugw("multicast-ip-to-mac-conversion-success",
2606 log.Fields{
2607 "ip:": ipv4Dst.(uint32),
2608 "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002609 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002610 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002611 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002612
David K. Bainbridge794735f2020-02-11 21:01:37 -08002613 onuID := NoneOnuID
2614 uniID := NoneUniID
2615 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00002616
David K. Bainbridge794735f2020-02-11 21:01:37 -08002617 flowStoreCookie := getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302618 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05302619 logger.Infow("multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002620 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002621 }
npujarec5762e2020-01-01 14:08:48 +05302622 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00002623 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302624 return olterrors.NewErrNotFound("multicast-flow-id",
2625 log.Fields{
2626 "interface-id": networkInterfaceID,
2627 "onu-id": onuID,
2628 "uni-id": uniID,
2629 "gem-port-id": gemPortID,
2630 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002631 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002632 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002633 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2634 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002635 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002636 }
2637 groupID := actionInfo[GroupID].(uint32)
2638 multicastFlow := openoltpb2.Flow{
2639 FlowId: flowID,
2640 FlowType: Multicast,
2641 NetworkIntfId: int32(networkInterfaceID),
2642 GroupId: groupID,
2643 Classifier: classifierProto,
2644 Priority: int32(flow.Priority),
2645 Cookie: flow.Cookie}
2646
David K. Bainbridge794735f2020-02-11 21:01:37 -08002647 if err = f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002648 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002649 }
Shrey Baid26912972020-04-16 21:02:31 +05302650 logger.Info("multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002651 //get cached group
2652 group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true)
2653 if err == nil {
2654 //calling groupAdd to set group members after multicast flow creation
Andrea Campanellac63bba92020-03-10 17:01:04 +01002655 if err = f.ModifyGroup(ctx, group); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002656 //cached group can be removed now
2657 f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002658 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002659 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002660 }
2661 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002662
2663 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2664 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2665 int32(onuID),
2666 int32(uniID),
2667 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002668 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002669 }
2670 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002671}
2672
Esin Karaman65409d82020-03-18 10:58:18 +00002673//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2674func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2675 if inPort, ok := classifierInfo[InPort]; ok {
2676 nniInterfaceID, err := IntfIDFromNniPortNum(inPort.(uint32))
2677 if err != nil {
2678 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2679 }
2680 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002681 }
Esin Karaman65409d82020-03-18 10:58:18 +00002682 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302683 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002684 if e == nil && len(nniPorts) > 0 {
2685 return nniPorts[0], nil
2686 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302687 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002688}
2689
2690// AddGroup add or update the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002691func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002692 logger.Infow("add-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002693 if group == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002694 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002695 }
2696
2697 groupToOlt := openoltpb2.Group{
2698 GroupId: group.Desc.GroupId,
2699 Command: openoltpb2.Group_SET_MEMBERS,
2700 Action: f.buildGroupAction(),
2701 }
2702
Shrey Baid26912972020-04-16 21:02:31 +05302703 logger.Debugw("sending-group-to-device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05302704 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002705 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002706 return olterrors.NewErrAdapter("add-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002707 }
2708 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05302709 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002710 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002711 }
Shrey Baid26912972020-04-16 21:02:31 +05302712 logger.Infow("add-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002713 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002714}
2715
2716//buildGroupAction creates and returns a group action
2717func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2718 var actionCmd openoltpb2.ActionCmd
2719 var action openoltpb2.Action
2720 action.Cmd = &actionCmd
2721 //pop outer vlan
2722 action.Cmd.RemoveOuterTag = true
2723 return &action
2724}
2725
2726// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002727func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002728 logger.Infow("modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002729 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002730 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002731 }
2732
Andrea Campanellac63bba92020-03-10 17:01:04 +01002733 newGroup := f.buildGroup(group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002734 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302735 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002736
2737 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002738 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002739 }
2740
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002741 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002742 if groupExists {
2743 // group already exists
2744 current = f.buildGroup(group.Desc.GroupId, val.Desc.GetBuckets())
Shrey Baid26912972020-04-16 21:02:31 +05302745 logger.Debugw("modify-group--group exists",
2746 log.Fields{
2747 "group on the device": val,
2748 "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002749 } else {
2750 current = f.buildGroup(group.Desc.GroupId, nil)
2751 }
2752
Shrey Baid26912972020-04-16 21:02:31 +05302753 logger.Debugw("modify-group--comparing-current-and-new",
2754 log.Fields{
2755 "group on the device": current,
2756 "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002757 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002758 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002759 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002760 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002761
Shrey Baid26912972020-04-16 21:02:31 +05302762 logger.Infow("modify-group--differences found", log.Fields{
2763 "membersToBeAdded": membersToBeAdded,
2764 "membersToBeRemoved": membersToBeRemoved,
2765 "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002766
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002767 groupToOlt := openoltpb2.Group{
2768 GroupId: group.Desc.GroupId,
2769 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002770 var errAdd, errRemoved error
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002771 if membersToBeAdded != nil && len(membersToBeAdded) > 0 {
2772 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2773 groupToOlt.Members = membersToBeAdded
2774 //execute addMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002775 errAdd = f.callGroupAddRemove(&groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002776 }
2777 if membersToBeRemoved != nil && len(membersToBeRemoved) > 0 {
2778 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2779 groupToOlt.Members = membersToBeRemoved
2780 //execute removeMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002781 errRemoved = f.callGroupAddRemove(&groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002782 }
2783
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002784 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002785 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302786 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002787 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002788 }
Shrey Baid26912972020-04-16 21:02:31 +05302789 logger.Infow("modify-group-was-success--storing-group",
2790 log.Fields{
2791 "group": group,
2792 "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002793 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302794 logger.Warnw("one-of-the-group-add/remove-operations-failed--cannot-save-group-modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002795 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002796 if errAdd != nil {
2797 return errAdd
2798 }
2799 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002800 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002801 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002802}
2803
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002804//callGroupAddRemove performs add/remove buckets operation for the indicated group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002805func (f *OpenOltFlowMgr) callGroupAddRemove(group *openoltpb2.Group) error {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002806 if err := f.performGroupOperation(group); err != nil {
2807 st, _ := status.FromError(err)
2808 //ignore already exists error code
2809 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002810 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002811 }
2812 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002813 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002814}
2815
2816//findDiff compares group members and finds members which only exists in groups2
2817func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2818 var members []*openoltpb2.GroupMember
2819 for _, bucket := range group2.Members {
2820 if !f.contains(group1.Members, bucket) {
2821 // bucket does not exist and must be added
2822 members = append(members, bucket)
2823 }
2824 }
2825 return members
2826}
2827
2828//contains returns true if the members list contains the given member; false otherwise
2829func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2830 for _, groupMember := range members {
2831 if groupMember.InterfaceId == member.InterfaceId {
2832 return true
2833 }
2834 }
2835 return false
2836}
2837
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002838//performGroupOperation call performGroupOperation operation of openolt proto
2839func (f *OpenOltFlowMgr) performGroupOperation(group *openoltpb2.Group) error {
Shrey Baid26912972020-04-16 21:02:31 +05302840 logger.Debugw("sending-group-to-device",
2841 log.Fields{
2842 "groupToOlt": group,
2843 "command": group.Command})
Esin Karamanccb714b2019-11-29 15:02:06 +00002844 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2845 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002846 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002847 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002848 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002849}
2850
2851//buildGroup build openoltpb2.Group from given group id and bucket list
2852func (f *OpenOltFlowMgr) buildGroup(groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
2853 group := openoltpb2.Group{
2854 GroupId: groupID}
2855 // create members of the group
2856 if buckets != nil {
2857 for _, ofBucket := range buckets {
2858 member := f.buildMember(ofBucket)
2859 if member != nil && !f.contains(group.Members, member) {
2860 group.Members = append(group.Members, member)
2861 }
2862 }
2863 }
2864 return &group
2865}
2866
2867//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
2868func (f *OpenOltFlowMgr) buildMember(ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
2869 var outPort uint32
2870 outPortFound := false
2871 for _, ofAction := range ofBucket.Actions {
2872 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2873 outPort = ofAction.GetOutput().Port
2874 outPortFound = true
2875 }
2876 }
2877
2878 if !outPortFound {
Shrey Baid26912972020-04-16 21:02:31 +05302879 logger.Debugw("bucket-skipped-since-no-out-port-found-in-it", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002880 return nil
2881 }
2882 interfaceID := IntfIDFromUniPortNum(outPort)
Shrey Baid26912972020-04-16 21:02:31 +05302883 logger.Debugw("got-associated-interface-id-of-the-port",
2884 log.Fields{
2885 "portNumber:": outPort,
2886 "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002887 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2888 member := openoltpb2.GroupMember{
2889 InterfaceId: interfaceID,
2890 InterfaceType: openoltpb2.GroupMember_PON,
2891 GemPortId: groupInfo.gemPortID,
2892 Priority: groupInfo.servicePriority,
2893 }
2894 //add member to the group
2895 return &member
2896 }
Shrey Baid26912972020-04-16 21:02:31 +05302897 logger.Warnf("bucket-skipped-since-interface-2-gem-mapping-cannot-be-found", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002898 return nil
2899}
2900
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002901//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04002902func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002903
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002904 onuDev, err := f.getOnuDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302905 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302906 logger.Errorw("couldnt-find-onu-child-device",
2907 log.Fields{
2908 "intf-id": intfID,
2909 "onu-id": onuID,
2910 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002911 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302912 }
Shrey Baid26912972020-04-16 21:02:31 +05302913 logger.Debugw("got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002914
Manikkaraj kb1d51442019-07-23 10:41:02 -04002915 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002916 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Matteo Scandolo92186242020-06-12 10:54:18 -07002917 logger.Debugw("sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
manikkaraj k17652a72019-05-06 09:06:36 -04002918 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2919 tpDownloadMsg,
2920 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302921 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002922 onuDev.deviceType,
2923 onuDev.deviceID,
2924 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002925 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302926 return olterrors.NewErrCommunication("send-techprofile-download-request",
2927 log.Fields{
2928 "from-adapter": f.deviceHandler.device.Type,
2929 "to-adapter": onuDev.deviceType,
2930 "onu-id": onuDev.deviceID,
2931 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002932 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002933 logger.Infow("success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302934 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302935}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002936
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302937//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002938func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302939
Matteo Scandolo60913ed2020-06-23 19:31:14 -07002940 f.onuGemInfoLock.Lock()
2941 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002942
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302943 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2944 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002945 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002946 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302947 }
Shrey Baid26912972020-04-16 21:02:31 +05302948 logger.Infow("updated-onuinfo",
2949 log.Fields{
2950 "intf-id": intfID,
2951 "onu-id": onuID,
2952 "serial-num": serialNum,
2953 "onu": onu,
2954 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002955 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002956}
2957
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302958//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302959func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002960
Matteo Scandolo60913ed2020-06-23 19:31:14 -07002961 f.onuGemInfoLock.Lock()
2962 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002963
Shrey Baid26912972020-04-16 21:02:31 +05302964 logger.Infow("adding-gem-to-onu-info-map",
2965 log.Fields{
Matteo Scandolo60913ed2020-06-23 19:31:14 -07002966 "gem-port-id": gemPort,
2967 "intf-id": intfID,
2968 "onu-id": onuID,
2969 "device-id": f.deviceHandler.device.Id,
2970 "onu-gem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302971 onugem := f.onuGemInfo[intfID]
2972 // update the gem to the local cache as well as to kv strore
2973 for idx, onu := range onugem {
2974 if onu.OnuID == onuID {
2975 // check if gem already exists , else update the cache and kvstore
2976 for _, gem := range onu.GemPorts {
2977 if gem == gemPort {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002978 logger.Debugw("gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302979 log.Fields{
2980 "gem": gemPort,
2981 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302982 return
2983 }
2984 }
2985 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2986 f.onuGemInfo[intfID] = onugem
2987 }
2988 }
npujarec5762e2020-01-01 14:08:48 +05302989 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302990 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302991 logger.Errorw("failed-to-add-gem-to-onu",
2992 log.Fields{
2993 "intf-id": intfID,
2994 "onu-id": onuID,
2995 "gemPort": gemPort,
2996 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002997 return
2998 }
Shrey Baid26912972020-04-16 21:02:31 +05302999 logger.Infow("gem-added-to-onu-info-map",
3000 log.Fields{
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003001 "gem-port-id": gemPort,
3002 "intf-id": intfID,
3003 "onu-id": onuID,
3004 "device-id": f.deviceHandler.device.Id,
3005 "onu-gem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003006}
3007
3008// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003009
3010//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003011func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303012
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003013 f.onuGemInfoLock.RLock()
3014 defer f.onuGemInfoLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303015
Matteo Scandoloa4e46912020-08-05 15:23:45 -07003016 logger.Debugw("getting-onu-id-from-gem-port-and-pon-port",
Shrey Baid26912972020-04-16 21:02:31 +05303017 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003018 "device-id": f.deviceHandler.device.Id,
3019 "onu-geminfo": f.onuGemInfo[intfID],
3020 "intf-id": intfID,
3021 "gemport-id": gemPortID})
Matteo Scandolod625b4c2020-04-02 16:16:01 -07003022
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303023 // get onuid from the onugem info cache
3024 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07003025
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303026 for _, onu := range onugem {
3027 for _, gem := range onu.GemPorts {
3028 if gem == gemPortID {
3029 return onu.OnuID, nil
3030 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003031 }
3032 }
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003033 logger.Errorw("onu-id-from-gem-port-not-found", log.Fields{
3034 "gem-port-id": gemPortID,
3035 "interface-id": intfID,
3036 "all-gems-on-port": onu,
3037 })
Thomas Lee S94109f12020-03-03 16:39:29 +05303038 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003039 "interface-id": intfID,
3040 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00003041 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003042}
3043
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003044//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05303045func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003046 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003047 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003048 var err error
3049
3050 if packetIn.IntfType == "pon" {
3051 // packet indication does not have serial number , so sending as nil
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003052 if onuID, err = f.getOnuIDfromGemPortMap(packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003053 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003054 return logicalPortNum, err
3055 }
3056 if packetIn.PortNo != 0 {
3057 logicalPortNum = packetIn.PortNo
3058 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003059 uniID := uint32(0) // FIXME - multi-uni support
3060 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003061 }
3062 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
Esin Karaman04166c82020-07-16 14:23:33 +00003063 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003064 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003065 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003066 }
Matteo Scandoloa4e46912020-08-05 15:23:45 -07003067 if logger.V(log.InfoLevel) {
3068 logger.Infow("retrieved-logicalport-from-packet-in",
3069 log.Fields{
3070 "logical-port-num": logicalPortNum,
3071 "intf-type": packetIn.IntfType,
3072 "packet": hex.EncodeToString(packetIn.Pkt),
3073 })
3074 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003075 return logicalPortNum, nil
3076}
3077
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003078//GetPacketOutGemPortID returns gemPortId
Esin Karaman04166c82020-07-16 14:23:33 +00003079func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003080 var gemPortID uint32
Esin Karaman04166c82020-07-16 14:23:33 +00003081
3082 ctag, priority, err := getCTagFromPacket(ctx, packet)
3083 if err != nil {
3084 return 0, err
3085 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303086
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003087 f.onuGemInfoLock.RLock()
3088 defer f.onuGemInfoLock.RUnlock()
Esin Karaman04166c82020-07-16 14:23:33 +00003089 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003090 var ok bool
3091 gemPortID, ok = f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303092 if ok {
Shrey Baid26912972020-04-16 21:02:31 +05303093 logger.Debugw("found-gemport-for-pktin-key",
3094 log.Fields{
3095 "pktinkey": pktInkey,
3096 "gem": gemPortID})
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003097
3098 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003099 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303100 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
Esin Karaman04166c82020-07-16 14:23:33 +00003101 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303102 if err == nil {
3103 if gemPortID != 0 {
3104 f.packetInGemPort[pktInkey] = gemPortID
Shrey Baid26912972020-04-16 21:02:31 +05303105 logger.Infow("found-gem-port-from-kv-store-and-updating-cache-with-gemport",
3106 log.Fields{
3107 "pktinkey": pktInkey,
3108 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303109 return gemPortID, nil
3110 }
3111 }
Shrey Baid26912972020-04-16 21:02:31 +05303112 return uint32(0), olterrors.NewErrNotFound("gem-port",
3113 log.Fields{
3114 "pktinkey": pktInkey,
3115 "gem": gemPortID}, err)
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003116
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003117}
3118
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003119// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303120func installFlowOnAllGemports(ctx context.Context,
3121 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003122 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003123 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05303124 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303125 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303126 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003127 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003128 args map[string]uint32,
3129 classifier map[string]interface{}, action map[string]interface{},
3130 logicalFlow *ofp.OfpFlowStats,
3131 gemPorts []uint32,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003132 TpInst interface{},
Manikkaraj kb1d51442019-07-23 10:41:02 -04003133 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00003134 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003135 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003136 vlanID ...uint32) {
Shrey Baid26912972020-04-16 21:02:31 +05303137 logger.Debugw("installing-flow-on-all-gem-ports",
3138 log.Fields{
3139 "FlowType": FlowType,
3140 "gemPorts": gemPorts,
3141 "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05303142
Gamze Abaka724d0852020-03-18 12:10:24 +00003143 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
3144 // We need to trim prefix "0b", before further processing
3145 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
3146 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
3147
3148 // If a particular character in the string is set to '1', identify the index of this character from
3149 // the LSB position which marks the PCP bit consumed by the given gem port.
3150 // This PCP bit now becomes a classifier in the flow.
3151
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003152 switch TpInst := TpInst.(type) {
3153 case *tp.TechProfile:
3154 attributes := TpInst.DownstreamGemPortAttributeList
3155 if direction == Upstream {
3156 attributes = TpInst.UpstreamGemPortAttributeList
Gamze Abaka724d0852020-03-18 12:10:24 +00003157 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003158
3159 for _, gemPortAttribute := range attributes {
3160 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
3161 continue
Gamze Abaka724d0852020-03-18 12:10:24 +00003162 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003163 gemPortID := gemPortAttribute.GemportID
3164 if allPbitsMarked(gemPortAttribute.PbitMap) {
3165 classifier[VlanPcp] = uint32(VlanPCPMask)
3166 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3167 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3168 } else if FlowType == EapolFlow {
3169 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3170 }
3171 } else {
3172 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
3173 if pbitSet == BinaryBit1 {
3174 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3175 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3176 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3177 } else if FlowType == EapolFlow {
3178 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3179 }
3180 }
3181 }
3182 }
3183 }
3184 case *tp.EponProfile:
3185 if direction == Upstream {
3186 attributes := TpInst.UpstreamQueueAttributeList
3187 for _, queueAttribute := range attributes {
3188 gemPortID := queueAttribute.GemportID
3189 if allPbitsMarked(queueAttribute.PbitMap) {
3190 classifier[VlanPcp] = uint32(VlanPCPMask)
Gamze Abaka724d0852020-03-18 12:10:24 +00003191 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003192 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003193 } else if FlowType == EapolFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003194 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 +00003195 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003196 } else {
3197 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3198 if pbitSet == BinaryBit1 {
3199 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3200 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3201 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3202 } else if FlowType == EapolFlow {
3203 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3204 }
3205 }
3206 }
3207 }
3208 }
3209 } else {
3210 attributes := TpInst.DownstreamQueueAttributeList
3211 for _, queueAttribute := range attributes {
3212 gemPortID := queueAttribute.GemportID
3213 if allPbitsMarked(queueAttribute.PbitMap) {
3214 classifier[VlanPcp] = uint32(VlanPCPMask)
3215 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3216 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3217 } else if FlowType == EapolFlow {
3218 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3219 }
3220 } else {
3221 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3222 if pbitSet == BinaryBit1 {
3223 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3224 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3225 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3226 } else if FlowType == EapolFlow {
3227 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3228 }
3229 }
3230 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05303231 }
3232 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04003233 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003234 default:
3235 logger.Errorw("unknown-tech", log.Fields{"tpInst": TpInst})
Manikkaraj kb1d51442019-07-23 10:41:02 -04003236 }
3237}
3238
Gamze Abaka724d0852020-03-18 12:10:24 +00003239func allPbitsMarked(pbitMap string) bool {
3240 for pos, pBit := range pbitMap {
3241 if pos >= 2 && pBit != BinaryBit1 {
3242 return false
3243 }
3244 }
3245 return true
3246}
3247
David K. Bainbridge794735f2020-02-11 21:01:37 -08003248func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05303249 logger.Debug("adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003250 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003251 classifier[PacketTagType] = DoubleTag
3252 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003253 /* We manage flowId resource pool on per PON port basis.
3254 Since this situation is tricky, as a hack, we pass the NNI port
3255 index (network_intf_id) as PON port Index for the flowId resource
3256 pool. Also, there is no ONU Id available for trapping DHCP packets
3257 on NNI port, use onu_id as -1 (invalid)
3258 ****************** CAVEAT *******************
3259 This logic works if the NNI Port Id falls within the same valid
3260 range of PON Port Ids. If this doesn't work for some OLT Vendor
3261 we need to have a re-look at this.
3262 *********************************************
3263 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003264 onuID := -1
3265 uniID := -1
3266 gemPortID := -1
3267 allocID := -1
David K. Bainbridge794735f2020-02-11 21:01:37 -08003268 networkInterfaceID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303269 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303270 return olterrors.NewErrNotFound("nni-intreface-id",
3271 log.Fields{
3272 "classifier": classifier,
3273 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003274 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303275 }
3276
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003277 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303278 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05303279 logger.Info("flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003280 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003281 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003282 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003283 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303284 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id",
3285 log.Fields{
3286 "interface-id": networkInterfaceID,
3287 "onu-id": onuID,
3288 "uni-id": uniID,
3289 "gem-port-id": gemPortID,
3290 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003291 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003292 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003293 classifierProto, err := makeOpenOltClassifierField(classifier)
3294 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003295 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003296 }
Shrey Baid26912972020-04-16 21:02:31 +05303297 logger.Debugw("created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003298 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003299 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003300 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003301 }
Shrey Baid26912972020-04-16 21:02:31 +05303302 logger.Debugw("created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003303 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3304 OnuId: int32(onuID), // OnuId not required
3305 UniId: int32(uniID), // UniId not used
3306 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07003307 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003308 AllocId: int32(allocID), // AllocId not used
3309 NetworkIntfId: int32(networkInterfaceID),
3310 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003311 Classifier: classifierProto,
3312 Action: actionProto,
3313 Priority: int32(logicalFlow.Priority),
3314 Cookie: logicalFlow.Cookie,
3315 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003316 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003317 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003318 }
Shrey Baid26912972020-04-16 21:02:31 +05303319 logger.Info("dhcp-trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003320 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3321 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3322 int32(onuID),
3323 int32(uniID),
3324 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003325 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003326 }
3327 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003328}
salmansiddiqui7ac62132019-08-22 03:58:50 +00003329
Esin Karamanae41e2b2019-12-17 18:13:13 +00003330//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
3331func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
3332 var packetType string
3333 ovid, ivid := false, false
3334 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
3335 vid := vlanID & VlanvIDMask
3336 if vid != ReservedVlan {
3337 ovid = true
3338 }
3339 }
3340 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
3341 vid := uint32(metadata)
3342 if vid != ReservedVlan {
3343 ivid = true
3344 }
3345 }
3346 if ovid && ivid {
3347 packetType = DoubleTag
3348 } else if !ovid && !ivid {
3349 packetType = Untagged
3350 } else {
3351 packetType = SingleTag
3352 }
3353 return packetType
3354}
3355
3356//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08003357func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05303358 logger.Infow("adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003359 action := make(map[string]interface{})
3360 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
3361 action[TrapToHost] = true
3362 /* We manage flowId resource pool on per PON port basis.
3363 Since this situation is tricky, as a hack, we pass the NNI port
3364 index (network_intf_id) as PON port Index for the flowId resource
3365 pool. Also, there is no ONU Id available for trapping packets
3366 on NNI port, use onu_id as -1 (invalid)
3367 ****************** CAVEAT *******************
3368 This logic works if the NNI Port Id falls within the same valid
3369 range of PON Port Ids. If this doesn't work for some OLT Vendor
3370 we need to have a re-look at this.
3371 *********************************************
3372 */
3373 onuID := -1
3374 uniID := -1
3375 gemPortID := -1
3376 allocID := -1
3377 networkInterfaceID, err := getNniIntfID(classifier, action)
3378 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303379 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003380 "classifier": classifier,
3381 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003382 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003383 }
3384 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303385 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05303386 logger.Info("igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003387 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003388 }
npujarec5762e2020-01-01 14:08:48 +05303389 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003390 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303391 return olterrors.NewErrNotFound("igmp-flow-id",
3392 log.Fields{
3393 "interface-id": networkInterfaceID,
3394 "onu-id": onuID,
3395 "uni-id": uniID,
3396 "gem-port-id": gemPortID,
3397 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003398 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003399 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003400 classifierProto, err := makeOpenOltClassifierField(classifier)
3401 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003402 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003403 }
Shrey Baid26912972020-04-16 21:02:31 +05303404 logger.Debugw("created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003405 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003406 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003407 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003408 }
Shrey Baid26912972020-04-16 21:02:31 +05303409 logger.Debugw("created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003410 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3411 OnuId: int32(onuID), // OnuId not required
3412 UniId: int32(uniID), // UniId not used
3413 FlowId: flowID,
3414 FlowType: Downstream,
3415 AllocId: int32(allocID), // AllocId not used
3416 NetworkIntfId: int32(networkInterfaceID),
3417 GemportId: int32(gemPortID), // GemportId not used
3418 Classifier: classifierProto,
3419 Action: actionProto,
3420 Priority: int32(logicalFlow.Priority),
3421 Cookie: logicalFlow.Cookie,
3422 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003423 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003424 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003425 }
Shrey Baid26912972020-04-16 21:02:31 +05303426 logger.Info("igmp-trap-on-nni-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003427 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3428 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3429 int32(onuID),
3430 int32(uniID),
3431 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003432 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003433 }
3434 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003435}
3436
salmansiddiqui7ac62132019-08-22 03:58:50 +00003437func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
3438 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05303439 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003440 }
3441 if Dir == tp_pb.Direction_UPSTREAM {
3442 return "upstream", nil
3443 } else if Dir == tp_pb.Direction_DOWNSTREAM {
3444 return "downstream", nil
3445 }
3446 return "", nil
3447}
3448
npujarec5762e2020-01-01 14:08:48 +05303449func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003450 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003451 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00003452 var gemPort uint32
3453 intfID := args[IntfID]
3454 onuID := args[OnuID]
3455 uniID := args[UniID]
3456 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003457 allocID := args[AllocID]
salmansiddiqui7ac62132019-08-22 03:58:50 +00003458 if ipProto, ok := classifierInfo[IPProto]; ok {
3459 if ipProto.(uint32) == IPProtoDhcp {
Matteo Scandolo92186242020-06-12 10:54:18 -07003460 logger.Infow("adding-dhcp-flow", log.Fields{
3461 "tp-id": tpID,
3462 "alloc-id": allocID,
3463 "intf-id": intfID,
3464 "onu-id": onuID,
3465 "uni-id": uniID,
3466 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003467 if pcp, ok := classifierInfo[VlanPcp]; ok {
3468 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3469 tp_pb.Direction_UPSTREAM,
3470 pcp.(uint32))
3471 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00003472
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003473 f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003474 } else {
3475 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003476 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003477 }
3478
Girish Gowdra32625212020-04-29 11:26:35 -07003479 } else if ipProto.(uint32) == IgmpProto {
Shrey Baid26912972020-04-16 21:02:31 +05303480 logger.Infow("adding-us-igmp-flow",
3481 log.Fields{
3482 "intf-id": intfID,
3483 "onu-id": onuID,
3484 "uni-id": uniID,
3485 "classifier-info:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003486 if pcp, ok := classifierInfo[VlanPcp]; ok {
3487 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3488 tp_pb.Direction_UPSTREAM,
3489 pcp.(uint32))
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003490 f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003491 } else {
3492 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003493 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003494 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003495 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303496 logger.Errorw("invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003497 return
3498 }
3499 } else if ethType, ok := classifierInfo[EthType]; ok {
3500 if ethType.(uint32) == EapEthType {
Matteo Scandolo92186242020-06-12 10:54:18 -07003501 logger.Infow("adding-eapol-flow", log.Fields{
3502 "intf-id": intfID,
3503 "onu-id": onuID,
3504 "uni-id": uniID,
3505 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003506 var vlanID uint32
3507 if val, ok := classifierInfo[VlanVid]; ok {
3508 vlanID = (val.(uint32)) & VlanvIDMask
3509 } else {
3510 vlanID = DefaultMgmtVlan
3511 }
3512 if pcp, ok := classifierInfo[VlanPcp]; ok {
3513 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3514 tp_pb.Direction_UPSTREAM,
3515 pcp.(uint32))
3516
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003517 f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003518 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003519 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003520 }
3521 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003522 } else if _, ok := actionInfo[PushVlan]; ok {
Matteo Scandolo92186242020-06-12 10:54:18 -07003523 logger.Infow("adding-upstream-data-rule", log.Fields{
3524 "intf-id": intfID,
3525 "onu-id": onuID,
3526 "uni-id": uniID,
3527 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003528 if pcp, ok := classifierInfo[VlanPcp]; ok {
3529 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3530 tp_pb.Direction_UPSTREAM,
3531 pcp.(uint32))
3532 //Adding HSIA upstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003533 f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003534 } else {
3535 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003536 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003537 }
3538 } else if _, ok := actionInfo[PopVlan]; ok {
Matteo Scandolo92186242020-06-12 10:54:18 -07003539 logger.Infow("adding-downstream-data-rule", log.Fields{
3540 "intf-id": intfID,
3541 "onu-id": onuID,
3542 "uni-id": uniID,
3543 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003544 if pcp, ok := classifierInfo[VlanPcp]; ok {
3545 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05003546 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003547 pcp.(uint32))
3548 //Adding HSIA downstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003549 f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003550 } else {
3551 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003552 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003553 }
3554 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303555 logger.Errorw("invalid-flow-type-to-handle",
3556 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003557 "intf-id": intfID,
3558 "onu-id": onuID,
3559 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05303560 "classifier": classifierInfo,
3561 "action": actionInfo,
3562 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003563 return
3564 }
3565 // Send Techprofile download event to child device in go routine as it takes time
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003566 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003567}
3568
Matteo Scandoloac032b12020-08-03 11:14:22 -07003569func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) (bool, error) {
3570 if f.perGemPortLock.TryLock(gemPK) {
3571 flowIDList := f.flowsUsedByGemPort[gemPK]
3572 f.perGemPortLock.Unlock(gemPK)
3573 if len(flowIDList) > 1 {
3574 return true, nil
3575 }
3576 return false, nil
Gamze Abakafee36392019-10-03 11:17:24 +00003577 }
Matteo Scandoloac032b12020-08-03 11:14:22 -07003578 logger.Error("failed-to-acquire-per-gem-port-lock",
3579 log.Fields{
3580 "device-id": f.deviceHandler.device.Id,
3581 "key": gemPK,
3582 })
3583 return false, olterrors.NewErrAdapter("failed-to-acquire-per-gem-port-lock", log.Fields{
3584 "device-id": f.deviceHandler.device.Id,
3585 "key": gemPK,
3586 }, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003587}
3588
npujarec5762e2020-01-01 14:08:48 +05303589func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3590 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003591 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3592 for _, currentGemPort := range currentGemPorts {
3593 for _, tpGemPort := range tpGemPorts {
3594 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3595 return true, currentGemPort
3596 }
3597 }
3598 }
Girish Gowdra54934262019-11-13 14:19:55 +05303599 if tpInst.InstanceCtrl.Onu == "single-instance" {
3600 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
npujarec5762e2020-01-01 14:08:48 +05303601 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID)
3602 f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID)
Girish Gowdra54934262019-11-13 14:19:55 +05303603
3604 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3605 // still be used on other uni ports.
3606 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3607 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003608 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Shrey Baid26912972020-04-16 21:02:31 +05303609 logger.Debugw("got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303610 for i := 0; i < len(tpInstances); i++ {
3611 tpI := tpInstances[i]
3612 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303613 for _, tpGemPort := range tpGemPorts {
3614 if tpGemPort.GemportID != gemPortID {
Shrey Baid26912972020-04-16 21:02:31 +05303615 logger.Debugw("single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303616 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303617 }
3618 }
3619 }
3620 }
Shrey Baid26912972020-04-16 21:02:31 +05303621 logger.Debug("tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003622 return false, 0
3623}
3624
salmansiddiqui7ac62132019-08-22 03:58:50 +00003625func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003626 for _, field := range flows.GetOfbFields(flow) {
3627 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003628 classifierInfo[EthType] = field.GetEthType()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003629 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003630 } else if field.Type == flows.ETH_DST {
3631 classifierInfo[EthDst] = field.GetEthDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003632 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003633 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003634 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003635 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003636 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003637 classifierInfo[InPort] = field.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003638 logger.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003639 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303640 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00003641 logger.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003642 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003643 classifierInfo[VlanPcp] = field.GetVlanPcp()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003644 logger.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003645 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003646 classifierInfo[UDPDst] = field.GetUdpDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003647 logger.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003648 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003649 classifierInfo[UDPSrc] = field.GetUdpSrc()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003650 logger.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003651 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003652 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003653 logger.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003654 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003655 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003656 logger.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003657 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003658 classifierInfo[Metadata] = field.GetTableMetadata()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003659 logger.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003660 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003661 classifierInfo[TunnelID] = field.GetTunnelId()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003662 logger.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003663 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303664 logger.Errorw("un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003665 return
3666 }
3667 }
3668}
3669
3670func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003671 for _, action := range flows.GetActions(flow) {
3672 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003673 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003674 actionInfo[Output] = out.GetPort()
Shrey Baid26912972020-04-16 21:02:31 +05303675 logger.Debugw("action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003676 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003677 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003678 }
Scott Baker355d1742019-10-24 10:57:52 -07003679 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003680 actionInfo[PopVlan] = true
Girish Kumar2ad402b2020-03-20 19:45:12 +00003681 logger.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003682 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003683 if out := action.GetPush(); out != nil {
3684 if tpid := out.GetEthertype(); tpid != 0x8100 {
Shrey Baid26912972020-04-16 21:02:31 +05303685 logger.Errorw("invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003686 } else {
3687 actionInfo[PushVlan] = true
3688 actionInfo[TPID] = tpid
Girish Kumar2ad402b2020-03-20 19:45:12 +00003689 logger.Debugw("action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303690 log.Fields{
3691 "push-tpid": actionInfo[TPID].(uint32),
3692 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003693 }
3694 }
Scott Baker355d1742019-10-24 10:57:52 -07003695 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003696 if out := action.GetSetField(); out != nil {
3697 if field := out.GetField(); field != nil {
3698 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003699 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003700 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00003701 /*logger.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
Esin Karamanccb714b2019-11-29 15:02:06 +00003702 formulateSetFieldActionInfoFromFlow(field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003703 }
3704 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003705 } else if action.Type == flows.GROUP {
3706 formulateGroupActionInfoFromFlow(action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003707 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003708 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003709 }
3710 }
3711 return nil
3712}
3713
Esin Karamanccb714b2019-11-29 15:02:06 +00003714func formulateSetFieldActionInfoFromFlow(field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
3715 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003716 fieldtype := ofbField.GetType()
3717 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003718 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3719 actionInfo[VlanVid] = vlan & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00003720 logger.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003721 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303722 logger.Error("no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003723 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003724 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3725 pcp := ofbField.GetVlanPcp()
3726 actionInfo[VlanPcp] = pcp
3727 log.Debugw("action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003728 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003729 logger.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003730 }
3731 }
3732}
3733
3734func formulateGroupActionInfoFromFlow(action *ofp.OfpAction, actionInfo map[string]interface{}) {
3735 if action.GetGroup() == nil {
Shrey Baid26912972020-04-16 21:02:31 +05303736 logger.Warn("no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003737 } else {
3738 actionInfo[GroupID] = action.GetGroup().GroupId
Girish Kumar2ad402b2020-03-20 19:45:12 +00003739 logger.Debugw("action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003740 }
3741}
3742
salmansiddiqui7ac62132019-08-22 03:58:50 +00003743func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003744 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Shrey Baid26912972020-04-16 21:02:31 +05303745 logger.Debug("controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003746 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3747 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003748 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003749 classifierInfo[InPort] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303750 logger.Debugw("upstream-pon-to-controller-flow--inport-in-tunnelid",
3751 log.Fields{
3752 "newinport": classifierInfo[InPort].(uint32),
3753 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003754 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303755 return olterrors.NewErrNotFound("child-in-port",
3756 log.Fields{
3757 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3758 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003759 }
3760 }
3761 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303762 logger.Debug("non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003763 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003764 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003765 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003766 actionInfo[Output] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303767 logger.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid",
3768 log.Fields{
3769 "newoutport": actionInfo[Output].(uint32),
3770 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003771 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303772 return olterrors.NewErrNotFound("out-port",
3773 log.Fields{
3774 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3775 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003776 }
3777 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3778 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003779 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003780 classifierInfo[InPort] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303781 logger.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid",
3782 log.Fields{
3783 "newinport": actionInfo[Output].(uint32),
3784 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003785 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303786 return olterrors.NewErrNotFound("nni-port",
3787 log.Fields{
3788 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3789 "in-port": classifierInfo[InPort].(uint32),
3790 "out-port": actionInfo[Output].(uint32),
3791 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003792 }
3793 }
3794 }
3795 return nil
3796}
Gamze Abakafee36392019-10-03 11:17:24 +00003797
Chaitrashree G S90a17952019-11-14 21:51:21 -05003798func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003799 /* Metadata 8 bytes:
3800 Most Significant 2 Bytes = Inner VLAN
3801 Next 2 Bytes = Tech Profile ID(TPID)
3802 Least Significant 4 Bytes = Port ID
3803 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3804 subscriber related flows.
3805 */
3806 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
3807 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003808 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003809 }
3810 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003811 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003812}
3813
3814func appendUnique(slice []uint32, item uint32) []uint32 {
3815 for _, sliceElement := range slice {
3816 if sliceElement == item {
3817 return slice
3818 }
3819 }
3820 return append(slice, item)
3821}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303822
3823// getNniIntfID gets nni intf id from the flow classifier/action
3824func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
3825
3826 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3827 if portType == voltha.Port_PON_OLT {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003828 intfID, err := IntfIDFromNniPortNum(action[Output].(uint32))
3829 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003830 logger.Debugw("invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003831 log.Fields{
3832 "port-number": action[Output].(uint32),
3833 "error": err})
3834 return uint32(0), err
3835 }
Shrey Baid26912972020-04-16 21:02:31 +05303836 logger.Infow("output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303837 return intfID, nil
3838 } else if portType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003839 intfID, err := IntfIDFromNniPortNum(classifier[InPort].(uint32))
3840 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003841 logger.Debugw("invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003842 log.Fields{
3843 "port-number": action[Output].(uint32),
3844 "error": err})
3845 return uint32(0), err
3846 }
Shrey Baid26912972020-04-16 21:02:31 +05303847 logger.Infow("input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303848 return intfID, nil
3849 }
3850 return uint32(0), nil
3851}
3852
3853// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman04166c82020-07-16 14:23:33 +00003854func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3855 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3856 if err != nil {
3857 logger.Errorw("unable-to-update-gem-port-for-packet-in",
3858 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3859 return
3860 }
3861 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003862
3863 f.onuGemInfoLock.Lock()
3864 defer f.onuGemInfoLock.Unlock()
3865
Matt Jeanneret1719a072019-12-20 14:50:14 -05003866 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303867 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003868 if lookupGemPort == gemPort {
Shrey Baid26912972020-04-16 21:02:31 +05303869 logger.Infow("pktin-key/value-found-in-cache--no-need-to-update-kv--assume-both-in-sync",
3870 log.Fields{
3871 "pktinkey": pktInkey,
3872 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003873 return
3874 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303875 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003876 f.packetInGemPort[pktInkey] = gemPort
3877
npujarec5762e2020-01-01 14:08:48 +05303878 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Shrey Baid26912972020-04-16 21:02:31 +05303879 logger.Infow("pktin-key-not-found-in-local-cache-value-is-different--updating-cache-and-kv-store",
3880 log.Fields{
3881 "pktinkey": pktInkey,
3882 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303883 return
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003884
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303885}
3886
Esin Karaman04166c82020-07-16 14:23:33 +00003887//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3888func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3889 if packet == nil || len(packet) < 18 {
3890 log.Error("unable-get-c-tag-from-the-packet--invalid-packet-length ")
3891 return 0, 0, errors.New("invalid packet length")
3892 }
3893 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3894 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3895
3896 var index int8
3897 if outerEthType == 0x8100 {
3898 if innerEthType == 0x8100 {
3899 // q-in-q 802.1ad or 802.1q double tagged packet.
3900 // get the inner vlanId
3901 index = 18
3902 } else {
3903 index = 14
3904 }
3905 priority := (packet[index] >> 5) & 0x7
3906 //13 bits composes vlanId value
3907 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3908 return vlan, priority, nil
3909 }
3910 logger.Debugf("No vlanId found in the packet. Returning zero as c-tag")
3911 return 0, 0, nil
3912}
3913
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303914// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303915func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003916
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003917 f.onuGemInfoLock.Lock()
3918 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003919
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303920 onugem := f.onuGemInfo[intfID]
3921 for idx, onu := range onugem {
3922 if onu.OnuID == onuID {
3923 for _, uni := range onu.UniPorts {
3924 if uni == portNum {
Shrey Baid26912972020-04-16 21:02:31 +05303925 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 +05303926 return
3927 }
3928 }
3929 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3930 f.onuGemInfo[intfID] = onugem
3931 }
3932 }
npujarec5762e2020-01-01 14:08:48 +05303933 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003934
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303935}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303936
npujarec5762e2020-01-01 14:08:48 +05303937func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3938 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303939 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303940 logger.Error("failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303941 return
3942 }
3943 for gem, FlowIDs := range flowIDsList {
3944 gemPK := gemPortKey{intf, uint32(gem)}
Matteo Scandoloac032b12020-08-03 11:14:22 -07003945 if f.perGemPortLock.TryLock(gemPK) {
3946 f.flowsUsedByGemPort[gemPK] = FlowIDs
3947 f.perGemPortLock.Unlock(gemPK)
3948 } else {
3949 logger.Error("failed-to-acquire-per-gem-port-lock",
3950 log.Fields{
3951 "intf-id": intf,
3952 "device-id": f.deviceHandler.device.Id,
3953 "key": gemPK,
3954 })
3955 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303956 }
3957 return
3958}
Esin Karamanccb714b2019-11-29 15:02:06 +00003959
3960//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
3961//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05303962func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
3963 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00003964 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303965 logger.Error("failed-to-get-pon-interface-to-multicast-queue-map")
Esin Karamanccb714b2019-11-29 15:02:06 +00003966 return
3967 }
3968 for intf, queueInfo := range storedMulticastQueueMap {
3969 q := queueInfoBrief{
3970 gemPortID: queueInfo[0],
3971 servicePriority: queueInfo[1],
3972 }
3973 f.interfaceToMcastQueueMap[intf] = &q
3974 }
3975}
3976
3977//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
3978//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
3979//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05303980func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
3981 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00003982 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003983 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00003984 }
3985 if exists {
3986 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
3987 }
3988 return nil, exists, nil
3989}
3990
3991func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
3992 groupDesc := ofp.OfpGroupDesc{
3993 Type: ofp.OfpGroupType_OFPGT_ALL,
3994 GroupId: groupID,
3995 }
3996 groupEntry := ofp.OfpGroupEntry{
3997 Desc: &groupDesc,
3998 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003999 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00004000 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00004001 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00004002 bucket := ofp.OfpBucket{
4003 Actions: acts,
4004 }
4005 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00004006 }
Esin Karamanccb714b2019-11-29 15:02:06 +00004007 return &groupEntry
4008}