blob: 521340574c71253b836587d876444e452a44a2bd [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
22 "crypto/md5"
Matteo Scandolo6056e822019-11-13 14:05:29 -080023 "encoding/hex"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "encoding/json"
Girish Gowdracefae192020-03-19 18:14:10 -070025 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053026 "fmt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040027 "math/big"
Girish Gowdrafae935c2020-02-17 19:21:44 +053028 "strings"
William Kurkian740a09c2019-10-23 17:07:38 -040029 "sync"
Girish Gowdra3d633032019-12-10 16:37:05 +053030 "time"
Manikkaraj kb1d51442019-07-23 10:41:02 -040031
Esin Karamanccb714b2019-11-29 15:02:06 +000032 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v3/pkg/log"
34 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080035 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000036 "github.com/opencord/voltha-protos/v3/go/common"
37 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
38 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
39 openoltpb2 "github.com/opencord/voltha-protos/v3/go/openolt"
40 tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
41 "github.com/opencord/voltha-protos/v3/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040042
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040043 //deepcopy "github.com/getlantern/deepcopy"
Girish Gowdra3d633032019-12-10 16:37:05 +053044 "github.com/EagleChen/mapmutex"
Thomas Lee S94109f12020-03-03 16:39:29 +053045 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000046 "google.golang.org/grpc/codes"
47 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053048)
49
50const (
51 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070053 //HsiaFlow flow category
54 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053055
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070056 //EapolFlow flow category
57 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053058
Manikkaraj kb1d51442019-07-23 10:41:02 -040059 //DhcpFlow flow category
60 DhcpFlow = "DHCP_FLOW"
61
Esin Karamanccb714b2019-11-29 15:02:06 +000062 //MulticastFlow flow category
63 MulticastFlow = "MULTICAST_FLOW"
64
Esin Karamanae41e2b2019-12-17 18:13:13 +000065 //IgmpFlow flow category
66 IgmpFlow = "IGMP_FLOW"
67
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068 //IPProtoDhcp flow category
69 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053070
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070071 //IPProtoIgmp flow category
72 IPProtoIgmp = 2
73
74 //EapEthType eapethtype value
75 EapEthType = 0x888e
76 //LldpEthType lldp ethtype value
77 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000078 //IPv4EthType IPv4 ethernet type value
79 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070080
81 //IgmpProto proto value
82 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053083
Andrea Campanella7acc0b92020-02-14 09:20:49 +010084 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
85 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040086
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087 //DefaultMgmtVlan default vlan value
88 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053089
manikkaraj kbf256be2019-03-25 00:13:48 +053090 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070091
David K. Bainbridge82efc492019-09-04 09:57:11 -070092 //Upstream constant
93 Upstream = "upstream"
94 //Downstream constant
95 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000096 //Multicast constant
97 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070098 //PacketTagType constant
99 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700100 //Untagged constant
101 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700102 //SingleTag constant
103 SingleTag = "single_tag"
104 //DoubleTag constant
105 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +0530106
107 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108
109 //EthType constant
110 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +0000111 //EthDst constant
112 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113 //TPID constant
114 TPID = "tpid"
115 //IPProto constant
116 IPProto = "ip_proto"
117 //InPort constant
118 InPort = "in_port"
119 //VlanVid constant
120 VlanVid = "vlan_vid"
121 //VlanPcp constant
122 VlanPcp = "vlan_pcp"
123
124 //UDPDst constant
125 UDPDst = "udp_dst"
126 //UDPSrc constant
127 UDPSrc = "udp_src"
128 //Ipv4Dst constant
129 Ipv4Dst = "ipv4_dst"
130 //Ipv4Src constant
131 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700132 //Metadata constant
133 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700134 //TunnelID constant
135 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700136 //Output constant
137 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000138 //GroupID constant
139 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700140 // Actions
141
142 //PopVlan constant
143 PopVlan = "pop_vlan"
144 //PushVlan constant
145 PushVlan = "push_vlan"
146 //TrapToHost constant
147 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400148 //MaxMeterBand constant
149 MaxMeterBand = 2
150 //VlanPCPMask contant
151 VlanPCPMask = 0xFF
152 //VlanvIDMask constant
153 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000154 //IntfID constant
155 IntfID = "intfId"
156 //OnuID constant
157 OnuID = "onuId"
158 //UniID constant
159 UniID = "uniId"
160 //PortNo constant
161 PortNo = "portNo"
162 //AllocID constant
163 AllocID = "allocId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000164
165 //NoneOnuID constant
166 NoneOnuID = -1
167 //NoneUniID constant
168 NoneUniID = -1
169 //NoneGemPortID constant
170 NoneGemPortID = -1
Girish Gowdrafae935c2020-02-17 19:21:44 +0530171
172 // BinaryStringPrefix is binary string prefix
173 BinaryStringPrefix = "0b"
174 // BinaryBit1 is binary bit 1 expressed as a character
175 BinaryBit1 = '1'
manikkaraj kbf256be2019-03-25 00:13:48 +0530176)
177
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400178type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700179 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400180 gemPort uint32
181}
182
Girish Gowdra3d633032019-12-10 16:37:05 +0530183type pendingFlowDeleteKey struct {
184 intfID uint32
185 onuID uint32
186 uniID uint32
187}
188
189type tpLockKey struct {
190 intfID uint32
191 onuID uint32
192 uniID uint32
193}
194
Gamze Abakafee36392019-10-03 11:17:24 +0000195type schedQueue struct {
196 direction tp_pb.Direction
197 intfID uint32
198 onuID uint32
199 uniID uint32
200 tpID uint32
201 uniPort uint32
202 tpInst *tp.TechProfile
203 meterID uint32
204 flowMetadata *voltha.FlowMetadata
205}
206
Esin Karamanccb714b2019-11-29 15:02:06 +0000207type queueInfoBrief struct {
208 gemPortID uint32
209 servicePriority uint32
210}
211
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700212//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530213type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000214 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000215 deviceHandler *DeviceHandler
216 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000217 onuIdsLock sync.RWMutex
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530218 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
219 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
220 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
221 lockCache sync.RWMutex
Girish Gowdra3d633032019-12-10 16:37:05 +0530222 pendingFlowDelete sync.Map
223 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Esin Karamanccb714b2019-11-29 15:02:06 +0000224 perUserFlowHandleLock *mapmutex.Mutex
225 interfaceToMcastQueueMap map[uint32]*queueInfoBrief /*pon interface -> multicast queue map. Required to assign GEM to a bucket during group population*/
manikkaraj kbf256be2019-03-25 00:13:48 +0530226}
227
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700228//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
npujarec5762e2020-01-01 14:08:48 +0530229func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700230 logger.Infow("Initializing flow manager", log.Fields{"deviceId": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530231 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530232 var err error
233 var idx uint32
234
manikkaraj kbf256be2019-03-25 00:13:48 +0530235 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530236 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000237 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530238 if err = flowMgr.populateTechProfilePerPonPort(); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000239 logger.Errorw("Error while populating tech profile mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530240 return nil
241 }
William Kurkian740a09c2019-10-23 17:07:38 -0400242 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530243 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
244 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
245 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo)
246 ponPorts := rMgr.DevInfo.GetPonPorts()
247 //Load the onugem info cache from kv store on flowmanager start
248 for idx = 0; idx < ponPorts; idx++ {
npujarec5762e2020-01-01 14:08:48 +0530249 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000250 logger.Error("Failed to load onu gem info cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530251 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530252 //Load flowID list per gem map per interface from the kvstore.
npujarec5762e2020-01-01 14:08:48 +0530253 flowMgr.loadFlowIDlistForGem(ctx, idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530254 }
255 flowMgr.lockCache = sync.RWMutex{}
Girish Gowdra3d633032019-12-10 16:37:05 +0530256 flowMgr.pendingFlowDelete = sync.Map{}
Girish Gowdrab77ded92020-04-08 11:45:05 -0700257 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(300, 100000000, 10000000, 1.1, 0.2)
Esin Karamanccb714b2019-11-29 15:02:06 +0000258 flowMgr.interfaceToMcastQueueMap = make(map[uint32]*queueInfoBrief)
259 //load interface to multicast queue map from kv store
npujarec5762e2020-01-01 14:08:48 +0530260 flowMgr.loadInterfaceToMulticastQueueMap(ctx)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000261 logger.Info("Initialization of flow manager success!!")
manikkaraj kbf256be2019-03-25 00:13:48 +0530262 return &flowMgr
263}
264
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700265func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700266 if direction == Upstream {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000267 logger.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700268 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700269 } else if direction == Downstream {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000270 logger.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700271 return uint64(flowID), nil
Esin Karamanccb714b2019-11-29 15:02:06 +0000272 } else if direction == Multicast {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000273 logger.Debug("multicast flow, shifting id")
Esin Karamanccb714b2019-11-29 15:02:06 +0000274 return 0x2<<15 | uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400275 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530276 return 0, olterrors.NewErrInvalidValue(log.Fields{"direction": direction}, nil).Log()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400277 }
278}
279
npujarec5762e2020-01-01 14:08:48 +0530280func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000281 logger.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700282 log.Fields{"device": f.deviceHandler.deviceID})
Gamze Abakafee36392019-10-03 11:17:24 +0000283 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
284 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
285 if !ok {
286 flowIDList = []uint32{deviceFlow.FlowId}
287 }
288 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
289 f.flowsUsedByGemPort[gemPK] = flowIDList
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530290 // update the flowids for a gem to the KVstore
npujarec5762e2020-01-01 14:08:48 +0530291 f.resourceMgr.UpdateFlowIDsForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400292}
293
npujarec5762e2020-01-01 14:08:48 +0530294func (f *OpenOltFlowMgr) divideAndAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000295 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
296 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000297 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530298 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400299 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530300
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700301 logger.Infow("dividing-flow", log.Fields{
302 "deviceId": f.deviceHandler.device.Id,
303 "intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
304 "classifier": classifierInfo,
305 "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400306 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
307 // is because the flow is an NNI flow and there would be no onu resources associated with it
308 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400309 if onuID <= 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000310 logger.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530311 return
312 }
313
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700314 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
315 logger.Debugw("uni-port-path", log.Fields{"uni": uni, "deviceId": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530316
317 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
318 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700319 logger.Debugw("dividing-flow-create-tcont-gem-ports", log.Fields{
320 "deviceId": f.deviceHandler.device.Id,
321 "intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
322 "classifier": classifierInfo,
323 "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
npujarec5762e2020-01-01 14:08:48 +0530324 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530325 if allocID == 0 || gemPorts == nil || TpInst == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000326 logger.Error("alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530327 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
328 return
329 }
330 args := make(map[string]uint32)
331 args[IntfID] = intfID
332 args[OnuID] = onuID
333 args[UniID] = uniID
334 args[PortNo] = portNo
335 args[AllocID] = allocID
336
337 /* Flows can be added specific to gemport if p-bits are received.
338 * If no pbit mentioned then adding flows for all gemports
339 */
npujarec5762e2020-01-01 14:08:48 +0530340 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530341 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
342 } else {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700343 logger.Errorw("failed-to-acquire-per-user-flow-handle-lock",
Girish Gowdra3d633032019-12-10 16:37:05 +0530344 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400345 return
346 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530347}
348
salmansiddiqui7ac62132019-08-22 03:58:50 +0000349// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530350func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400351
Girish Kumar2ad402b2020-03-20 19:45:12 +0000352 logger.Debugw("CreateSchedulerQueues", log.Fields{"Dir": sq.direction, "IntfID": sq.intfID,
Gamze Abakafee36392019-10-03 11:17:24 +0000353 "OnuID": sq.onuID, "UniID": sq.uniID, "TpID": sq.tpID, "MeterID": sq.meterID,
354 "TpInst": sq.tpInst, "flowMetadata": sq.flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400355
Gamze Abakafee36392019-10-03 11:17:24 +0000356 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000357 if err != nil {
358 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400359 }
360
361 /* Lets make a simple assumption that if the meter-id is present on the KV store,
362 * then the scheduler and queues configuration is applied on the OLT device
363 * in the given direction.
364 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000365
Manikkaraj kb1d51442019-07-23 10:41:02 -0400366 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530367 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400368 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000369 return olterrors.NewErrNotFound("meter", log.Fields{"intfId": sq.intfID, "onuId": sq.onuID, "uniId": sq.uniID}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400370 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000371
Manikkaraj kb1d51442019-07-23 10:41:02 -0400372 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000373 if KvStoreMeter.MeterId == sq.meterID {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000374 logger.Debug("Scheduler already created for upstream")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400375 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400376 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530377 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800378 "unsupported": "meter-id",
379 "kv-store-meter-id": KvStoreMeter.MeterId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000380 "meter-id-in-flow": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400381 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000382
Girish Kumar2ad402b2020-03-20 19:45:12 +0000383 logger.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": sq.meterID, "Direction": Direction})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000384
Gamze Abakafee36392019-10-03 11:17:24 +0000385 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000386 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Gamze Abakafee36392019-10-03 11:17:24 +0000387 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000388 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400389 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000390
391 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000392 return olterrors.NewErrNotFound("scheduler-config", log.Fields{"IntfID": sq.intfID, "Direction": sq.direction, "tpInst": sq.tpInst}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000393 }
394
Manikkaraj kb1d51442019-07-23 10:41:02 -0400395 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000396 if sq.flowMetadata != nil {
397 for _, meter := range sq.flowMetadata.Meters {
398 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400399 meterConfig = meter
Girish Kumar2ad402b2020-03-20 19:45:12 +0000400 logger.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401 break
402 }
403 }
404 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000405 logger.Error("Flow-metadata-is-not-present-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400406 }
407 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530408 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800409 "reason": "Could-not-get-meterbands-from-flowMetadata",
410 "flow-metadata": sq.flowMetadata,
Girish Kumarf26e4882020-03-05 06:49:10 +0000411 "meter-id": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400412 } else if len(meterConfig.Bands) < MaxMeterBand {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000413 logger.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": sq.meterID})
Thomas Lee S94109f12020-03-03 16:39:29 +0530414 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800415 "reason": "Invalid-number-of-bands-in-meter",
416 "meterband-count": len(meterConfig.Bands),
417 "metabands": meterConfig.Bands,
Girish Kumarf26e4882020-03-05 06:49:10 +0000418 "meter-id": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400419 }
420 cir := meterConfig.Bands[0].Rate
421 cbs := meterConfig.Bands[0].BurstSize
422 eir := meterConfig.Bands[1].Rate
423 ebs := meterConfig.Bands[1].BurstSize
424 pir := cir + eir
425 pbs := cbs + ebs
426 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
427
Gamze Abakafee36392019-10-03 11:17:24 +0000428 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400429
npujarec5762e2020-01-01 14:08:48 +0530430 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000431 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device", log.Fields{"intfID": sq.intfID, "direction": sq.direction}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 }
433
salmansiddiqui7ac62132019-08-22 03:58:50 +0000434 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400435 * store the meter id on the KV store, for further reference.
436 */
npujarec5762e2020-01-01 14:08:48 +0530437 if err := f.resourceMgr.UpdateMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000438 return olterrors.NewErrAdapter("failed-updating-meter-id", log.Fields{"onu-id": sq.onuID, "meter-id": sq.meterID}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400439 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000440 logger.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400441 "Meter": meterConfig})
442 return nil
443}
444
npujarec5762e2020-01-01 14:08:48 +0530445func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000446
447 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
448
449 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000450 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration", log.Fields{"intfID": sq.intfID, "direction": sq.direction}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000451 }
452
Girish Kumar2ad402b2020-03-20 19:45:12 +0000453 logger.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": sq.direction, "TrafficScheds": TrafficSched})
npujarec5762e2020-01-01 14:08:48 +0530454 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000455 IntfId: sq.intfID, OnuId: sq.onuID,
456 UniId: sq.uniID, PortNo: sq.uniPort,
457 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000458 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000459 }
460
461 // On receiving the CreateTrafficQueues request, the driver should create corresponding
462 // downstream queues.
Girish Kumar2ad402b2020-03-20 19:45:12 +0000463 logger.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": sq.direction, "TrafficQueues": trafficQueues})
npujarec5762e2020-01-01 14:08:48 +0530464 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000465 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
466 UniId: sq.uniID, PortNo: sq.uniPort,
467 TrafficQueues: trafficQueues}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000468 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"TrafficQueues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000469 }
470
Esin Karamanccb714b2019-11-29 15:02:06 +0000471 if sq.direction == tp_pb.Direction_DOWNSTREAM {
472 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(sq.tpInst)
473 if len(multicastTrafficQueues) > 0 {
474 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
475 //assumed that there is only one queue per PON for the multicast service
476 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
477 //just put it in interfaceToMcastQueueMap to use for building group members
478 multicastQueuePerPonPort := multicastTrafficQueues[0]
479 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
480 gemPortID: multicastQueuePerPonPort.GemportId,
481 servicePriority: multicastQueuePerPonPort.Priority,
482 }
483 //also store the queue info in kv store
npujarec5762e2020-01-01 14:08:48 +0530484 f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID,
Esin Karamanccb714b2019-11-29 15:02:06 +0000485 multicastQueuePerPonPort.GemportId,
486 multicastQueuePerPonPort.Priority)
487 }
488 }
489 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000490 return nil
491}
492
salmansiddiqui7ac62132019-08-22 03:58:50 +0000493// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530494func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400495
496 var Direction string
497 var SchedCfg *tp_pb.SchedulerConfig
498 var err error
Girish Kumar2ad402b2020-03-20 19:45:12 +0000499 logger.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": sq.direction, "IntfID": sq.intfID,
Gamze Abakafee36392019-10-03 11:17:24 +0000500 "OnuID": sq.onuID, "UniID": sq.uniID, "UniPort": sq.uniPort})
501 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000502 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000504 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000505 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400506 Direction = "downstream"
507 }
508
Girish Kumar8f73fe02019-12-09 13:19:37 +0000509 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000510 return olterrors.NewErrNotFound("scheduler-config", log.Fields{"IntID": sq.intfID, "Direction": sq.direction}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000511 }
512
npujarec5762e2020-01-01 14:08:48 +0530513 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400514 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000515 return olterrors.NewErrNotFound("meter", log.Fields{"onuID": sq.onuID}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400516 }
517 if KVStoreMeter == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000518 logger.Debugw("No-meter-has-been-installed-yet", log.Fields{"direction": Direction, "IntfID": sq.intfID, "OnuID": sq.onuID, "UniID": sq.uniID})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400519 return nil
520 }
521 cir := KVStoreMeter.Bands[0].Rate
522 cbs := KVStoreMeter.Bands[0].BurstSize
523 eir := KVStoreMeter.Bands[1].Rate
524 ebs := KVStoreMeter.Bands[1].BurstSize
525 pir := cir + eir
526 pbs := cbs + ebs
527
528 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
529
Gamze Abakafee36392019-10-03 11:17:24 +0000530 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Girish Kumar8f73fe02019-12-09 13:19:37 +0000531
532 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
533 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000534 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration", log.Fields{"intfID": sq.intfID, "direction": sq.direction}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000535 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400536
npujarec5762e2020-01-01 14:08:48 +0530537 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000538 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
539 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400540 TrafficQueues: TrafficQueues}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000541 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
542 log.Fields{"intfID": sq.intfID, "TrafficQueues": TrafficQueues}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400543 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000544 logger.Debug("Removed traffic queues successfully")
npujarec5762e2020-01-01 14:08:48 +0530545 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000546 IntfId: sq.intfID, OnuId: sq.onuID,
547 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400548 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000549 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
550 log.Fields{"intfID": sq.intfID, "TrafficSchedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400551 }
552
Girish Kumar2ad402b2020-03-20 19:45:12 +0000553 logger.Debug("Removed traffic schedulers successfully")
salmansiddiqui7ac62132019-08-22 03:58:50 +0000554
555 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400556 * delete the meter id on the KV store.
557 */
npujarec5762e2020-01-01 14:08:48 +0530558 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400559 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000560 return olterrors.NewErrAdapter("unable-to-remove-meter", log.Fields{"onu": sq.onuID, "meter": KVStoreMeter.MeterId}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400561 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000562 logger.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400563 return err
564}
565
Gamze Abakafee36392019-10-03 11:17:24 +0000566// This function allocates tconts and GEM ports for an ONU
npujarec5762e2020-01-01 14:08:48 +0530567func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) (uint32, []uint32, *tp.TechProfile) {
Gamze Abakafee36392019-10-03 11:17:24 +0000568 var allocIDs []uint32
569 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530570 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530571 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000572 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000573
npujarec5762e2020-01-01 14:08:48 +0530574 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
575 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400576
577 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530578
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700579 logger.Infow("creating-new-tcont-and-gem", log.Fields{
580 "pon": intfID, "onu": onuID, "uni": uniID,
581 "deviceId": f.deviceHandler.device.Id, "tpId": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530582
Manikkaraj kb1d51442019-07-23 10:41:02 -0400583 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530584 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000585 if techProfileInstance == nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700586 logger.Infow("tp-instance-not-found--creating-new", log.Fields{"path": tpPath, "deviceId": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530587 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000588 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530589 // This should not happen, something wrong in KV backend transaction
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700590 logger.Errorw("tp-instance-create-failed", log.Fields{"error": err, "tpID": TpID, "deviceId": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000591 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530592 }
npujarec5762e2020-01-01 14:08:48 +0530593 f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530594 } else {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700595 logger.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni, "deviceId": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530596 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530597 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400598 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000599 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
600 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530601 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700602 logger.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID, "deviceId": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000603 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400604 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530605 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400606 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000607 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
608 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530609 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700610 logger.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID, "deviceId": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000611 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400612 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530613 }
Gamze Abakafee36392019-10-03 11:17:24 +0000614
615 allocID := techProfileInstance.UsScheduler.AllocID
Gamze Abakafee36392019-10-03 11:17:24 +0000616 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Gamze Abakafee36392019-10-03 11:17:24 +0000617 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400618 }
Gamze Abakafee36392019-10-03 11:17:24 +0000619
Girish Gowdra3d633032019-12-10 16:37:05 +0530620 if tpInstanceExists {
621 return allocID, gemPortIDs, techProfileInstance
622 }
623
624 allocIDs = appendUnique(allocIDs, allocID)
625 for _, gemPortID := range gemPortIDs {
626 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
627 }
628
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700629 logger.Debugw("allocated-tcont-and-GEM-ports", log.Fields{"allocIDs": allocIDs, "gemports": allgemPortIDs, "deviceId": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530630 // Send Tconts and GEM ports to KV store
npujarec5762e2020-01-01 14:08:48 +0530631 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000632 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530633}
634
npujarec5762e2020-01-01 14:08:48 +0530635func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530636
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700637 logger.Debugw("storing-allocated-Tconts-and-GEM-ports-into-KV-store",
638 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs, "deviceId": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530639 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530640 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000641 logger.Error("Errow while uploading allocID to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530642 }
npujarec5762e2020-01-01 14:08:48 +0530643 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000644 logger.Error("Errow while uploading GEMports to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530645 }
npujarec5762e2020-01-01 14:08:48 +0530646 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000647 logger.Error("Errow while uploading gemtopon map to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530648 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700649 logger.Debugw("stored-tconts-and-GEM-into-KV-store-successfully", log.Fields{"deviceId": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400650 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530651 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400652 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530653}
654
655func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000656 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530657 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000658 for _, intfID := range techRange.IntfIds {
659 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400660 tpCount++
Girish Kumar2ad402b2020-03-20 19:45:12 +0000661 logger.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530662 }
663 }
664 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400665 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530666 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800667 "reason": "TP count does not match number of PON ports",
668 "tech-profile-count": tpCount,
Girish Kumarf26e4882020-03-05 06:49:10 +0000669 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts()}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530670 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000671 logger.Infow("Populated techprofile for ponports successfully",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400672 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530673 return nil
674}
675
npujarec5762e2020-01-01 14:08:48 +0530676func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530677 portNo uint32, uplinkClassifier map[string]interface{},
678 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800679 allocID uint32, gemportID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700680 uplinkClassifier[PacketTagType] = SingleTag
Girish Kumar2ad402b2020-03-20 19:45:12 +0000681 logger.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800682 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700683 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530684 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530685}
686
npujarec5762e2020-01-01 14:08:48 +0530687func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530688 portNo uint32, downlinkClassifier map[string]interface{},
689 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800690 allocID uint32, gemportID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700691 downlinkClassifier[PacketTagType] = DoubleTag
Girish Kumar2ad402b2020-03-20 19:45:12 +0000692 logger.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
Manikkaraj k884c1242019-04-11 16:26:42 +0530693 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400694 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
695 if vlan, exists := downlinkClassifier[VlanVid]; exists {
696 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700697 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400698 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000699 logger.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800700 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400701 }
702 }
703 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530704 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400705
Manikkaraj k884c1242019-04-11 16:26:42 +0530706 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700707 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400708 // vlan_vid is a uint32. must be type asserted as such or conversion fails
709 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530710 if ok {
711 downlinkAction[VlanVid] = dlClVid & 0xfff
712 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530713 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800714 "reason": "failed to convert VLANID classifier",
715 "vlan-id": VlanVid}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530716 }
717
David K. Bainbridge794735f2020-02-11 21:01:37 -0800718 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700719 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530720}
721
npujarec5762e2020-01-01 14:08:48 +0530722func (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 +0530723 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800724 allocID uint32, gemPortID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530725 /* One of the OLT platform (Broadcom BAL) requires that symmetric
726 flows require the same flow_id to be used across UL and DL.
727 Since HSIA flow is the only symmetric flow currently, we need to
728 re-use the flow_id across both direction. The 'flow_category'
729 takes priority over flow_cookie to find any available HSIA_FLOW
730 id for the ONU.
731 */
Girish Kumar2ad402b2020-03-20 19:45:12 +0000732 logger.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700733 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530734 "logicalFlow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530735 var vlanPbit uint32 = 0xff // means no pbit
Gamze Abaka724d0852020-03-18 12:10:24 +0000736 var vlanVid uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400737 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000738 vlanPbit = classifier[VlanPcp].(uint32)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000739 logger.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800740 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000741 logger.Debugw("pbit-not-found-in-flow", log.Fields{"vlan-pcp": VlanPcp})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400742 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000743 if _, ok := classifier[VlanVid]; ok {
744 vlanVid = classifier[VlanVid].(uint32)
745 log.Debugw("Found vlan in the flow", log.Fields{"VlanVid": vlanVid})
746 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700747 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530748 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000749 logger.Debug("flow-already-exists")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800750 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530751 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000752 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530753 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530754 return olterrors.NewErrNotFound("hsia-flow-id", log.Fields{"direction": direction}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530755 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800756 classifierProto, err := makeOpenOltClassifierField(classifier)
757 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530758 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530759 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000760 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +0000761 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800762 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530763 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530764 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000765 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800766 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530767 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530768 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800769 log.Fields{
770 "classifier": classifier,
771 "action": action,
772 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530773 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700774 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
775 OnuId: int32(onuID),
776 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000777 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530778 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700779 AllocId: int32(allocID),
780 NetworkIntfId: int32(networkIntfID),
781 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530782 Classifier: classifierProto,
783 Action: actionProto,
784 Priority: int32(logicalFlow.Priority),
785 Cookie: logicalFlow.Cookie,
786 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800787 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530788 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530789 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000790 logger.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800791 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
792 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
793 flow.OnuId,
794 flow.UniId,
795 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530796 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": flow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800797 }
798 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +0530799}
Esin Karamanae41e2b2019-12-17 18:13:13 +0000800
David K. Bainbridge794735f2020-02-11 21:01:37 -0800801func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530802
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530803 networkIntfID, err := getNniIntfID(classifier, action)
804 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530805 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800806 "classifier": classifier,
807 "action": action},
808 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530809 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530810
811 // Clear the action map
812 for k := range action {
813 delete(action, k)
814 }
815
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700816 action[TrapToHost] = true
817 classifier[UDPSrc] = uint32(68)
818 classifier[UDPDst] = uint32(67)
819 classifier[PacketTagType] = SingleTag
820 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530821
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700822 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530823 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000824 logger.Debug("Flow-exists--not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800825 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530826 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530827
David K. Bainbridge794735f2020-02-11 21:01:37 -0800828 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 +0530829
830 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530831 return olterrors.NewErrNotFound("flow", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800832 "interface-id": intfID,
833 "gem-port": gemPortID,
834 "cookie": flowStoreCookie},
835 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530836 }
837
Girish Kumar2ad402b2020-03-20 19:45:12 +0000838 logger.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530839
David K. Bainbridge794735f2020-02-11 21:01:37 -0800840 classifierProto, err := makeOpenOltClassifierField(classifier)
841 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530842 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530843 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000844 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +0000845 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800846 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530847 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530848 }
849
David K. Bainbridge794735f2020-02-11 21:01:37 -0800850 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700851 OnuId: int32(onuID),
852 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530853 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700854 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700855 AllocId: int32(allocID),
856 NetworkIntfId: int32(networkIntfID),
857 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530858 Classifier: classifierProto,
859 Action: actionProto,
860 Priority: int32(logicalFlow.Priority),
861 Cookie: logicalFlow.Cookie,
862 PortNo: portNo}
863
David K. Bainbridge794735f2020-02-11 21:01:37 -0800864 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530865 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800866 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000867 logger.Debug("DHCP UL flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800868 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
869 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
870 dhcpFlow.OnuId,
871 dhcpFlow.UniId,
872 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530873 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId, log.Fields{"flow": dhcpFlow}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530874 }
875
David K. Bainbridge794735f2020-02-11 21:01:37 -0800876 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530877}
878
Esin Karamanae41e2b2019-12-17 18:13:13 +0000879//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +0530880func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
David K. Bainbridge794735f2020-02-11 21:01:37 -0800881 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32) error {
882 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow)
Esin Karamanae41e2b2019-12-17 18:13:13 +0000883}
884
885//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +0530886func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
David K. Bainbridge794735f2020-02-11 21:01:37 -0800887 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +0000888
889 networkIntfID, err := getNniIntfID(classifier, action)
890 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530891 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800892 "classifier": classifier,
893 "action": action},
894 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000895 }
896
897 // Clear the action map
898 for k := range action {
899 delete(action, k)
900 }
901
902 action[TrapToHost] = true
903 classifier[PacketTagType] = SingleTag
904 delete(classifier, VlanVid)
905
906 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530907 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000908 logger.Debug("Flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800909 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +0000910 }
911
npujarec5762e2020-01-01 14:08:48 +0530912 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 +0000913
914 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530915 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800916 "interface-id": intfID,
917 "oni-id": onuID,
918 "cookie": flowStoreCookie,
919 "flow-type": flowType},
920 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000921 }
922
Girish Kumar2ad402b2020-03-20 19:45:12 +0000923 logger.Debugw("Creating upstream trap flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID, "flowType": flowType})
Esin Karamanae41e2b2019-12-17 18:13:13 +0000924
David K. Bainbridge794735f2020-02-11 21:01:37 -0800925 classifierProto, err := makeOpenOltClassifierField(classifier)
926 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530927 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000928 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000929 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +0000930 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800931 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530932 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000933 }
934
David K. Bainbridge794735f2020-02-11 21:01:37 -0800935 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +0000936 OnuId: int32(onuID),
937 UniId: int32(uniID),
938 FlowId: flowID,
939 FlowType: Upstream,
940 AllocId: int32(allocID),
941 NetworkIntfId: int32(networkIntfID),
942 GemportId: int32(gemPortID),
943 Classifier: classifierProto,
944 Action: actionProto,
945 Priority: int32(logicalFlow.Priority),
946 Cookie: logicalFlow.Cookie,
947 PortNo: portNo}
948
David K. Bainbridge794735f2020-02-11 21:01:37 -0800949 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530950 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": flow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800951 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000952 logger.Debugf("%s UL flow added to device successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +0000953
David K. Bainbridge794735f2020-02-11 21:01:37 -0800954 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
955 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
956 flow.OnuId,
957 flow.UniId,
958 flow.FlowId, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530959 return olterrors.NewErrPersistence("update", "flow", flow.FlowId, log.Fields{"flow": flow}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000960 }
961
David K. Bainbridge794735f2020-02-11 21:01:37 -0800962 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +0000963}
964
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700965// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Girish Gowdrafae935c2020-02-17 19:21:44 +0530966func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000967 logger.Debugw("Adding EAPOL to device", log.Fields{"intfId": intfID, "onuId": onuID, "portNo": portNo, "allocId": allocID, "gemPortId": gemPortID, "vlanId": vlanID, "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +0530968
969 uplinkClassifier := make(map[string]interface{})
970 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +0530971
manikkaraj kbf256be2019-03-25 00:13:48 +0530972 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700973 uplinkClassifier[EthType] = uint32(EapEthType)
974 uplinkClassifier[PacketTagType] = SingleTag
975 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +0000976 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +0530977 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700978 uplinkAction[TrapToHost] = true
979 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530980 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000981 logger.Debug("Flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800982 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530983 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530984 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +0000985 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530986 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530987 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800988 "interface-id": intfID,
989 "onu-id": onuID,
990 "coookie": flowStoreCookie},
991 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +0530992 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000993 logger.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530994
David K. Bainbridge794735f2020-02-11 21:01:37 -0800995 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
996 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530997 return olterrors.NewErrInvalidValue(log.Fields{"classifier": uplinkClassifier}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +0530998 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000999 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001000 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001001 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301002 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301003 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001004 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001005 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301006 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301007 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001008 "classifier": classifier,
1009 "action": action},
1010 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301011 }
1012
David K. Bainbridge794735f2020-02-11 21:01:37 -08001013 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001014 OnuId: int32(onuID),
1015 UniId: int32(uniID),
1016 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001017 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001018 AllocId: int32(allocID),
1019 NetworkIntfId: int32(networkIntfID),
1020 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301021 Classifier: classifierProto,
1022 Action: actionProto,
1023 Priority: int32(logicalFlow.Priority),
1024 Cookie: logicalFlow.Cookie,
1025 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001026 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301027 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001028 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001029 logger.Debug("EAPOL UL flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001030 flowCategory := "EAPOL"
1031 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1032 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1033 upstreamFlow.OnuId,
1034 upstreamFlow.UniId,
1035 upstreamFlow.FlowId,
1036 /* lowCategory, */
1037 flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301038 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId, log.Fields{"flow": upstreamFlow}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301039 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301040
Girish Kumar2ad402b2020-03-20 19:45:12 +00001041 logger.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001042 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301043}
1044
David K. Bainbridge794735f2020-02-11 21:01:37 -08001045func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001046 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001047
1048 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1049 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1050 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001051 if vlanID != ReservedVlan {
1052 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001053 classifier.OVid = vid
1054 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301055 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001056 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1057 vid := uint32(metadata)
1058 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001059 classifier.IVid = vid
1060 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301061 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301062 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001063 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301064 classifier.OPbits = vlanPcp
1065 } else {
1066 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301067 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001068 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1069 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1070 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1071 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001072 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001073 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1074 classifier.PktTagType = pktTagType
1075
1076 switch pktTagType {
1077 case SingleTag:
1078 case DoubleTag:
1079 case Untagged:
1080 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001081 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301082 }
1083 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001084 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301085}
1086
Gamze Abaka724d0852020-03-18 12:10:24 +00001087func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001088 var actionCmd openoltpb2.ActionCmd
1089 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301090 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001091 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301092 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001093 if _, ok := actionInfo[VlanPcp]; ok {
1094 action.Cmd.RemarkInnerPbits = true
1095 action.IPbits = actionInfo[VlanPcp].(uint32)
1096 if _, ok := actionInfo[VlanVid]; ok {
1097 action.Cmd.TranslateInnerTag = true
1098 action.IVid = actionInfo[VlanVid].(uint32)
1099 }
1100 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001101 } else if _, ok := actionInfo[PushVlan]; ok {
1102 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301103 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001104 if _, ok := actionInfo[VlanPcp]; ok {
1105 action.OPbits = actionInfo[VlanPcp].(uint32)
1106 action.Cmd.RemarkOuterPbits = true
1107 if _, ok := classifierInfo[VlanVid]; ok {
1108 action.IVid = classifierInfo[VlanVid].(uint32)
1109 action.Cmd.TranslateInnerTag = true
1110 }
1111 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001112 } else if _, ok := actionInfo[TrapToHost]; ok {
1113 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301114 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001115 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301116 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001117 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301118}
1119
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001120// getTPpath return the ETCD path for a given UNI port
1121func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uniPath string, TpID uint32) string {
1122 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301123}
1124
Gamze Abakafee36392019-10-03 11:17:24 +00001125// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301126func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1127 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001128 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1129
Gamze Abakafee36392019-10-03 11:17:24 +00001130 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301131 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001132 olterrors.NewErrAdapter("delete-tech-profile-failed", nil, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301133 // return err
1134 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001135 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001136 log.Debugw("tech-profile-deleted", log.Fields{"deviceId": f.deviceHandler.device.Id, "tp": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001137 }
1138 return nil
1139}
1140
1141// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301142func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001143 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001144 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001145 }
npujarec5762e2020-01-01 14:08:48 +05301146 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001147 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001148 }
1149 return nil
1150}
1151
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001152func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301153 if len(classifier) == 0 { // should never happen
Girish Kumar2ad402b2020-03-20 19:45:12 +00001154 logger.Error("Invalid classfier object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301155 return 0
1156 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001157 logger.Debugw("generating flow store cookie", log.Fields{"classifier": classifier, "gemPortID": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301158 var jsonData []byte
1159 var flowString string
1160 var err error
1161 // TODO: Do we need to marshall ??
1162 if jsonData, err = json.Marshal(classifier); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001163 logger.Error("Failed to encode classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301164 return 0
1165 }
1166 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001167 if gemPortID != 0 {
1168 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301169 }
1170 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001171 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301172 hash := big.NewInt(0)
1173 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301174 generatedHash := hash.Uint64()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001175 logger.Debugw("hash generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301176 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301177}
1178
npujarec5762e2020-01-01 14:08:48 +05301179func (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 +05301180 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001181 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001182 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1183 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1184 */
1185 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001186 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001187 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001188 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001189 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001190 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301191 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001192 if existingFlows != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001193 logger.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001194 //for _, f := range *existingFlows {
1195 // flows = append(flows, f)
1196 //}
1197 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001198 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001199 logger.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
manikkaraj kbf256be2019-03-25 00:13:48 +05301200 return &flows
1201}
1202
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001203//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1204// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1205// var intfId uint32
1206// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1207// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1208// */
1209// if flow.AccessIntfId != -1 {
1210// intfId = uint32(flow.AccessIntfId)
1211// } else {
1212// intfId = uint32(flow.NetworkIntfId)
1213// }
1214// // Get existing flows matching flowid for given subscriber from KV store
1215// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1216// if existingFlows != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001217// logger.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001218// for _, f := range *existingFlows {
1219// flows = append(flows, f)
1220// }
1221// }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001222// logger.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001223// return &flows
1224//}
1225
npujarec5762e2020-01-01 14:08:48 +05301226func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(ctx context.Context, intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001227 logger.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
npujarec5762e2020-01-01 14:08:48 +05301228 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001229 logger.Debug("Error while Storing flow into KV store")
manikkaraj k17652a72019-05-06 09:06:36 -04001230 return err
1231 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001232 logger.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301233 return nil
1234}
1235
David K. Bainbridge794735f2020-02-11 21:01:37 -08001236func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001237
1238 var intfID uint32
1239 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1240 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1241 */
1242 if deviceFlow.AccessIntfId != -1 {
1243 intfID = uint32(deviceFlow.AccessIntfId)
1244 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001245 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001246 intfID = uint32(deviceFlow.NetworkIntfId)
1247 }
1248
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001249 logger.Debugw("sending-flow-to-device-via-grpc", log.Fields{
1250 "flow": *deviceFlow,
1251 "deviceId": f.deviceHandler.device.Id,
1252 })
manikkaraj kbf256be2019-03-25 00:13:48 +05301253 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001254
1255 st, _ := status.FromError(err)
1256 if st.Code() == codes.AlreadyExists {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001257 logger.Debug("flow-already-exists", log.Fields{
1258 "err": err,
1259 "deviceFlow": deviceFlow,
1260 "deviceId": f.deviceHandler.device.Id,
1261 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001262 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301263 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001264
1265 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001266 logger.Errorw("failed-to-Add-flow-to-device", log.Fields{
1267 "err": err,
1268 "deviceFlow": deviceFlow,
1269 "deviceId": f.deviceHandler.device.Id,
1270 })
npujarec5762e2020-01-01 14:08:48 +05301271 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001272 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001273 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301274 if deviceFlow.GemportId != -1 {
1275 // No need to register the flow if it is a trap on nni flow.
npujarec5762e2020-01-01 14:08:48 +05301276 f.registerFlow(ctx, logicalFlow, deviceFlow)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301277 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001278 logger.Debugw("flow-added-to-device-successfully", log.Fields{
1279 "flow": *deviceFlow,
1280 "deviceId": f.deviceHandler.device.Id,
1281 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001282 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001283}
1284
David K. Bainbridge794735f2020-02-11 21:01:37 -08001285func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001286 logger.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001287 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1288 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001289 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001290 logger.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
serkant.uluderya245caba2019-09-24 23:15:29 -07001291 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001292 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001293 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001294 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001295
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001296 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001297 logger.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001298 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301299}
1300
1301/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1302 //update core flows_proxy : flows_proxy.update('/', flows)
1303}
1304
1305func generateStoredId(flowId uint32, direction string)uint32{
1306
David K. Bainbridge82efc492019-09-04 09:57:11 -07001307 if direction == Upstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001308 logger.Debug("Upstream flow shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301309 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001310 }else if direction == Downstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001311 logger.Debug("Downstream flow not shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301312 return flowId
1313 }else{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001314 logger.Errorw("Unrecognized direction",log.Fields{"direction": direction})
manikkaraj kbf256be2019-03-25 00:13:48 +05301315 return flowId
1316 }
1317}
1318
1319*/
1320
David K. Bainbridge794735f2020-02-11 21:01:37 -08001321func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001322
1323 classifierInfo := make(map[string]interface{})
1324 actionInfo := make(map[string]interface{})
1325
1326 classifierInfo[EthType] = uint32(LldpEthType)
1327 classifierInfo[PacketTagType] = Untagged
1328 actionInfo[TrapToHost] = true
1329
1330 // LLDP flow is installed to trap LLDP packets on the NNI port.
1331 // We manage flow_id resource pool on per PON port basis.
1332 // Since this situation is tricky, as a hack, we pass the NNI port
1333 // index (network_intf_id) as PON port Index for the flow_id resource
1334 // pool. Also, there is no ONU Id available for trapping LLDP packets
1335 // on NNI port, use onu_id as -1 (invalid)
1336 // ****************** CAVEAT *******************
1337 // This logic works if the NNI Port Id falls within the same valid
1338 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1339 // we need to have a re-look at this.
1340 // *********************************************
1341
1342 var onuID = -1
1343 var uniID = -1
1344 var gemPortID = -1
1345
David K. Bainbridge794735f2020-02-11 21:01:37 -08001346 networkInterfaceID, err := IntfIDFromNniPortNum(portNo)
1347 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301348 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001349 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001350 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301351 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001352 logger.Debug("Flow-exists--not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001353 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001354 }
npujarec5762e2020-01-01 14:08:48 +05301355 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001356
1357 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301358 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001359 "interface-id": networkInterfaceID,
1360 "onu-id": onuID,
1361 "uni-id": uniID,
1362 "gem-port-id": gemPortID,
1363 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00001364 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001365 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001366 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1367 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001368 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001369 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001370 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001371 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001372 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001373 return olterrors.NewErrInvalidValue(log.Fields{"action": actionInfo}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001374 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001375 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
Humera Kouser94d7a842019-08-25 19:04:32 -04001376
1377 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1378 OnuId: int32(onuID), // OnuId not required
1379 UniId: int32(uniID), // UniId not used
1380 FlowId: flowID,
1381 FlowType: Downstream,
1382 NetworkIntfId: int32(networkInterfaceID),
1383 GemportId: int32(gemPortID),
1384 Classifier: classifierProto,
1385 Action: actionProto,
1386 Priority: int32(flow.Priority),
1387 Cookie: flow.Cookie,
1388 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001389 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001390 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001391 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001392 logger.Debug("LLDP trap on NNI flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001393 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1394 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1395 int32(onuID),
1396 int32(uniID),
1397 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001398 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001399 }
1400 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301401}
1402
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001403func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1404 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001405}
1406
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001407//getOnuDevice to fetch onu from cache or core.
1408func (f *OpenOltFlowMgr) getOnuDevice(intfID uint32, onuID uint32) (*OnuDevice, error) {
1409 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1410 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1411 if !ok {
1412 logger.Debugw("couldnt-find-onu-in-cache", log.Fields{"intfID": intfID, "onuID": onuID})
1413 onuDevice, err := f.getChildDevice(intfID, onuID)
1414 if err != nil {
1415 return nil, olterrors.NewErrNotFound("onu-child-device", log.Fields{"onuId": onuID, "intfID": intfID}, err)
1416 }
1417 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1418 //better to ad the device to cache here.
1419 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1420 } else {
1421 logger.Debugw("Found-onu-in-cache", log.Fields{"intfID": intfID, "onuID": onuID})
1422 }
1423
1424 return onuDev.(*OnuDevice), nil
1425}
1426
1427//getChildDevice to fetch onu
1428func (f *OpenOltFlowMgr) getChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001429 logger.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001430 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001431 onuDevice, err := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
1432 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301433 return nil, olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001434 "interface-id": parentPortNo,
1435 "onu-id": onuID},
Girish Kumarf26e4882020-03-05 06:49:10 +00001436 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301437 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001438 logger.Debugw("Successfully received child device from core", log.Fields{"child_device_id": onuDevice.Id, "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301439 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301440}
1441
1442func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001443 logger.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301444 return nil
1445}
1446
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001447func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001448 logger.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301449}
1450
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001451func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001452 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001453 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001454 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001455 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001456}
1457
Girish Gowdra6b130582019-11-20 16:45:20 +05301458func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001459 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301460 if err != nil {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001461 logger.Debugw("couldnt-find-onu-child-device", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1462 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301463 }
1464
1465 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001466 logger.Debugw("sending gem port delete to openonu adapter", log.Fields{"msg": *delGemPortMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301467 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1468 delGemPortMsg,
1469 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
1470 f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001471 onuDev.deviceType,
1472 onuDev.deviceID,
1473 onuDev.proxyDeviceID, ""); sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001474 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001475 "toAdapter": onuDev.deviceType, "onuId": onuDev.deviceID,
1476 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301477 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001478 logger.Debugw("success sending del gem port to onu adapter", log.Fields{"msg": delGemPortMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301479 return nil
1480}
1481
1482func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001483 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301484 if err != nil {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001485 logger.Debugw("couldnt-find-onu-child-device", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1486 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301487 }
1488
1489 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001490 logger.Debugw("sending tcont delete to openonu adapter", log.Fields{"msg": *delTcontMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301491 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1492 delTcontMsg,
1493 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
1494 f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001495 onuDev.deviceType,
1496 onuDev.deviceID,
1497 onuDev.proxyDeviceID, ""); sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001498 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001499 "toAdapter": onuDev.deviceType, "onuId": onuDev.deviceID,
1500 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301501 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001502 logger.Debugw("success sending del tcont to onu adapter", log.Fields{"msg": delTcontMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301503 return nil
1504}
1505
Girish Gowdra3d633032019-12-10 16:37:05 +05301506func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1507 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1508 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1509 if val.(int) > 0 {
1510 pnFlDels := val.(int) - 1
1511 if pnFlDels > 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001512 logger.Debugw("flow delete succeeded, more pending",
Girish Gowdra3d633032019-12-10 16:37:05 +05301513 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1514 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1515 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001516 logger.Debugw("all pending flow deletes handled, removing entry from map",
Girish Gowdra3d633032019-12-10 16:37:05 +05301517 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1518 f.pendingFlowDelete.Delete(pnFlDelKey)
1519 }
1520 }
1521 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001522 logger.Debugw("no pending delete flows found",
Girish Gowdra3d633032019-12-10 16:37:05 +05301523 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1524
1525 }
1526
1527}
1528
Girish Gowdrac3037402020-01-22 20:29:53 +05301529// Once the gemport is released for a given onu, it also has to be cleared from local cache
1530// which was used for deriving the gemport->logicalPortNo during packet-in.
1531// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1532// is conveyed to ONOS during packet-in OF message.
1533func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(intfID uint32, onuID uint32, gemPortID uint32) {
1534 f.lockCache.Lock()
1535 defer f.lockCache.Unlock()
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001536 logger.Debugw("deleting-gem-from-local-cache",
1537 log.Fields{"gem": gemPortID, "intf": intfID, "onu": onuID, "deviceId": f.deviceHandler.device.Id, "onuGem": f.onuGemInfo[intfID]})
Girish Gowdrac3037402020-01-22 20:29:53 +05301538 onugem := f.onuGemInfo[intfID]
serkant.uluderya96af4932020-02-20 16:58:48 -08001539 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301540 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001541 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301542 // If the gemport is found, delete it from local cache.
1543 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001544 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1545 onugem[i] = onu
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001546 logger.Debugw("removed-gemport-from-local-cache",
1547 log.Fields{"intfID": intfID, "onuID": onuID, "deletedGemPortID": gemPortID, "gemPorts": onu.GemPorts, "deviceId": f.deviceHandler.device.Id})
Girish Gowdrac3037402020-01-22 20:29:53 +05301548 break
1549 }
1550 }
1551 break
1552 }
1553 }
1554}
1555
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301556//clearResources clears pon resources in kv store and the device
npujarec5762e2020-01-01 14:08:48 +05301557func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301558 gemPortID int32, flowID uint32, flowDirection string,
1559 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001560
Chaitrashree G S90a17952019-11-14 21:51:21 -05001561 tpID, err := getTpIDFromFlow(flow)
1562 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001563 return olterrors.NewErrNotFound("tpid", log.Fields{"flow": flow, "pon": Intf, "onuID": onuID, "uniID": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001564 }
Gamze Abakafee36392019-10-03 11:17:24 +00001565
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001566 if len(updatedFlows) >= 0 {
1567 // There are still flows referencing the same flow_id.
1568 // So the flow should not be freed yet.
1569 // For ex: Case of HSIA where same flow is shared
1570 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00001571 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
1572 olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": updatedFlows}, err).Log()
1573 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001574 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05301575 // Do this for subscriber flows only (not trap from NNI flows)
1576 if onuID != -1 && uniID != -1 {
1577 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1578 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001579 logger.Debugw("creating entry for pending flow delete",
Girish Gowdra3d633032019-12-10 16:37:05 +05301580 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1581 f.pendingFlowDelete.Store(pnFlDelKey, 1)
1582 } else {
1583 pnFlDels := val.(int) + 1
Girish Kumar2ad402b2020-03-20 19:45:12 +00001584 logger.Debugw("updating flow delete entry",
Girish Gowdra3d633032019-12-10 16:37:05 +05301585 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1586 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1587 }
1588
1589 defer f.deletePendingFlows(Intf, onuID, uniID)
1590 }
1591
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001592 logger.Debugw("releasing-flow-id-to-resource-manager", log.Fields{
1593 "Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID,
1594 "deviceId": f.deviceHandler.device.Id,
1595 })
npujarec5762e2020-01-01 14:08:48 +05301596 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001597
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001598 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301599 tpPath := f.getTPpath(Intf, uni, tpID)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001600 logger.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
npujarec5762e2020-01-01 14:08:48 +05301601 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00001602 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1603 return olterrors.NewErrNotFound("tech-profile-in-kv-store", log.Fields{"tpID": tpID, "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00001604 }
1605
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301606 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001607 if f.isGemPortUsedByAnotherFlow(gemPK) {
1608 flowIDs := f.flowsUsedByGemPort[gemPK]
1609 for i, flowIDinMap := range flowIDs {
1610 if flowIDinMap == flowID {
1611 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301612 // everytime flowsUsedByGemPort cache is updated the same should be updated
1613 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001614 f.flowsUsedByGemPort[gemPK] = flowIDs
npujarec5762e2020-01-01 14:08:48 +05301615 f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00001616 break
1617 }
1618 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001619 logger.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301620 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001621 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001622 logger.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301623 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001624 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1625 // 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 +05301626 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Girish Gowdrac3037402020-01-22 20:29:53 +05301627 f.deleteGemPortFromLocalCache(Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001628 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301629 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1630 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001631 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05301632 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1633 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001634 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05301635 // Delete the gem port on the ONU.
1636 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001637 logger.Errorw("error processing delete gem-port towards onu",
Girish Gowdra6b130582019-11-20 16:45:20 +05301638 log.Fields{"err": err, "pon": Intf, "onuID": onuID, "uniID": uniID, "gemPortId": gemPortID})
1639 }
Gamze Abakafee36392019-10-03 11:17:24 +00001640
npujarec5762e2020-01-01 14:08:48 +05301641 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001642 if !ok {
npujarec5762e2020-01-01 14:08:48 +05301643 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
1644 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1645 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1646 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
1647 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301648 // Delete the TCONT on the ONU.
1649 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001650 logger.Errorw("error processing delete tcont towards onu",
Girish Gowdra6b130582019-11-20 16:45:20 +05301651 log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID, "allocId": techprofileInst.UsScheduler.AllocID})
1652 }
Gamze Abakafee36392019-10-03 11:17:24 +00001653 }
1654 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001655 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301656 return nil
1657}
1658
David K. Bainbridge794735f2020-02-11 21:01:37 -08001659// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301660func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301661
Girish Kumar2ad402b2020-03-20 19:45:12 +00001662 logger.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
Esin Karamanccb714b2019-11-29 15:02:06 +00001663
1664 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05301665 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001666 return
1667 }
1668
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301669 var updatedFlows []rsrcMgr.FlowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301670 classifierInfo := make(map[string]interface{})
1671
1672 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1673 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001674 logger.Error(err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301675 return
1676 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301677
David K. Bainbridge794735f2020-02-11 21:01:37 -08001678 onuID := int32(onu)
1679 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301680
1681 for _, field := range flows.GetOfbFields(flow) {
1682 if field.Type == flows.IP_PROTO {
1683 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001684 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301685 }
1686 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001687 logger.Debugw("Extracted access info from flow to be deleted",
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301688 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1689
1690 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1691 onuID = -1
1692 uniID = -1
Girish Kumar2ad402b2020-03-20 19:45:12 +00001693 logger.Debug("Trap on nni flow set oni, uni to -1")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001694 Intf, err = IntfIDFromNniPortNum(inPort)
1695 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001696 logger.Errorw("invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001697 log.Fields{
1698 "port-number": inPort,
1699 "error": err})
1700 return
1701 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301702 }
npujarec5762e2020-01-01 14:08:48 +05301703 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001704 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05301705 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301706 if flowInfo == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001707 logger.Debugw("No FlowInfo found found in KV store",
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301708 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1709 return
1710 }
1711 updatedFlows = nil
1712 for _, flow := range *flowInfo {
1713 updatedFlows = append(updatedFlows, flow)
1714 }
1715
1716 for i, storedFlow := range updatedFlows {
1717 if flow.Id == storedFlow.LogicalFlowID {
1718 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001719 logger.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001720 // DKB
1721 if err = f.removeFlowFromDevice(&removeFlowMessage); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001722 logger.Errorw("failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001723 return
1724 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001725 logger.Debug("Flow removed from device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001726 //Remove the Flow from FlowInfo
1727 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1728 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1729 flowID, flowDirection, portNum, updatedFlows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001730 logger.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301731 return
1732 }
1733 }
1734 }
1735 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001736}
1737
Esin Karamanccb714b2019-11-29 15:02:06 +00001738//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
1739// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05301740func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00001741 classifierInfo := make(map[string]interface{})
1742 formulateClassifierInfoFromFlow(classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00001743 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00001744
1745 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001746 logger.Warnw("No inPort found. Cannot release resources of the multicast flow.", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001747 return
1748 }
1749
Esin Karamanccb714b2019-11-29 15:02:06 +00001750 var onuID = int32(NoneOnuID)
1751 var uniID = int32(NoneUniID)
1752 var flowID uint32
1753 var updatedFlows []rsrcMgr.FlowInfo
1754
npujarec5762e2020-01-01 14:08:48 +05301755 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001756
1757 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05301758 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001759 if flowInfo == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001760 logger.Debugw("No multicast FlowInfo found in the KV store",
Esin Karamanccb714b2019-11-29 15:02:06 +00001761 log.Fields{"Intf": networkInterfaceID, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1762 continue
1763 }
1764 updatedFlows = nil
1765 for _, flow := range *flowInfo {
1766 updatedFlows = append(updatedFlows, flow)
1767 }
1768 for i, storedFlow := range updatedFlows {
1769 if flow.Id == storedFlow.LogicalFlowID {
1770 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001771 logger.Debugw("Multicast flow to be deleted", log.Fields{"flow": storedFlow})
Esin Karamanccb714b2019-11-29 15:02:06 +00001772 //remove from device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001773 if err := f.removeFlowFromDevice(&removeFlowMessage); err != nil {
1774 // DKB
Girish Kumar2ad402b2020-03-20 19:45:12 +00001775 logger.Errorw("failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001776 log.Fields{
1777 "flow-id": flow.Id,
1778 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001779 return
1780 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001781 logger.Debugw("Multicast flow removed from device successfully", log.Fields{"flowId": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001782 //Remove the Flow from FlowInfo
1783 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05301784 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001785 logger.Error("Failed to delete multicast flow from the KV store", log.Fields{"flow": storedFlow, "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001786 return
1787 }
1788 //release flow id
Girish Kumar2ad402b2020-03-20 19:45:12 +00001789 logger.Debugw("Releasing multicast flow id", log.Fields{"flowId": flowID, "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05301790 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001791 }
1792 }
1793 }
1794}
1795
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001796//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07001797func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001798 logger.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301799 var direction string
1800