blob: 546ac95684a27fed7485496bc8af00787f35bb57 [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 {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000230 logger.Info("Initializing flow manager")
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 Gowdrade2739e2020-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
Girish Kumar2ad402b2020-03-20 19:45:12 +0000301 logger.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000302 "classifier": classifierInfo, "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400303 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
304 // is because the flow is an NNI flow and there would be no onu resources associated with it
305 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400306 if onuID <= 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000307 logger.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530308 return
309 }
310
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530311 uni := getUniPortPath(intfID, int32(onuID), int32(uniID))
Girish Kumar2ad402b2020-03-20 19:45:12 +0000312 logger.Debugw("Uni port name", log.Fields{"uni": uni})
Girish Gowdra3d633032019-12-10 16:37:05 +0530313
314 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
315 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
npujarec5762e2020-01-01 14:08:48 +0530316 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530317 if allocID == 0 || gemPorts == nil || TpInst == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000318 logger.Error("alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530319 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
320 return
321 }
322 args := make(map[string]uint32)
323 args[IntfID] = intfID
324 args[OnuID] = onuID
325 args[UniID] = uniID
326 args[PortNo] = portNo
327 args[AllocID] = allocID
328
329 /* Flows can be added specific to gemport if p-bits are received.
330 * If no pbit mentioned then adding flows for all gemports
331 */
npujarec5762e2020-01-01 14:08:48 +0530332 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530333 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
334 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000335 logger.Errorw("failed to acquire per user flow handle lock",
Girish Gowdra3d633032019-12-10 16:37:05 +0530336 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400337 return
338 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530339}
340
salmansiddiqui7ac62132019-08-22 03:58:50 +0000341// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530342func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400343
Girish Kumar2ad402b2020-03-20 19:45:12 +0000344 logger.Debugw("CreateSchedulerQueues", log.Fields{"Dir": sq.direction, "IntfID": sq.intfID,
Gamze Abakafee36392019-10-03 11:17:24 +0000345 "OnuID": sq.onuID, "UniID": sq.uniID, "TpID": sq.tpID, "MeterID": sq.meterID,
346 "TpInst": sq.tpInst, "flowMetadata": sq.flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400347
Gamze Abakafee36392019-10-03 11:17:24 +0000348 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000349 if err != nil {
350 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400351 }
352
353 /* Lets make a simple assumption that if the meter-id is present on the KV store,
354 * then the scheduler and queues configuration is applied on the OLT device
355 * in the given direction.
356 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000357
Manikkaraj kb1d51442019-07-23 10:41:02 -0400358 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530359 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400360 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000361 return olterrors.NewErrNotFound("meter", log.Fields{"intfId": sq.intfID, "onuId": sq.onuID, "uniId": sq.uniID}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400362 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000363
Manikkaraj kb1d51442019-07-23 10:41:02 -0400364 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000365 if KvStoreMeter.MeterId == sq.meterID {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000366 logger.Debug("Scheduler already created for upstream")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400367 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400368 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530369 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800370 "unsupported": "meter-id",
371 "kv-store-meter-id": KvStoreMeter.MeterId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000372 "meter-id-in-flow": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400373 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000374
Girish Kumar2ad402b2020-03-20 19:45:12 +0000375 logger.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": sq.meterID, "Direction": Direction})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000376
Gamze Abakafee36392019-10-03 11:17:24 +0000377 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000378 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Gamze Abakafee36392019-10-03 11:17:24 +0000379 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000380 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400381 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000382
383 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000384 return olterrors.NewErrNotFound("scheduler-config", log.Fields{"IntfID": sq.intfID, "Direction": sq.direction, "tpInst": sq.tpInst}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000385 }
386
Manikkaraj kb1d51442019-07-23 10:41:02 -0400387 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000388 if sq.flowMetadata != nil {
389 for _, meter := range sq.flowMetadata.Meters {
390 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400391 meterConfig = meter
Girish Kumar2ad402b2020-03-20 19:45:12 +0000392 logger.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400393 break
394 }
395 }
396 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000397 logger.Error("Flow-metadata-is-not-present-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400398 }
399 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530400 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800401 "reason": "Could-not-get-meterbands-from-flowMetadata",
402 "flow-metadata": sq.flowMetadata,
Girish Kumarf26e4882020-03-05 06:49:10 +0000403 "meter-id": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400404 } else if len(meterConfig.Bands) < MaxMeterBand {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000405 logger.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": sq.meterID})
Thomas Lee S94109f12020-03-03 16:39:29 +0530406 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800407 "reason": "Invalid-number-of-bands-in-meter",
408 "meterband-count": len(meterConfig.Bands),
409 "metabands": meterConfig.Bands,
Girish Kumarf26e4882020-03-05 06:49:10 +0000410 "meter-id": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400411 }
412 cir := meterConfig.Bands[0].Rate
413 cbs := meterConfig.Bands[0].BurstSize
414 eir := meterConfig.Bands[1].Rate
415 ebs := meterConfig.Bands[1].BurstSize
416 pir := cir + eir
417 pbs := cbs + ebs
418 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
419
Gamze Abakafee36392019-10-03 11:17:24 +0000420 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400421
npujarec5762e2020-01-01 14:08:48 +0530422 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000423 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 -0400424 }
425
salmansiddiqui7ac62132019-08-22 03:58:50 +0000426 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400427 * store the meter id on the KV store, for further reference.
428 */
npujarec5762e2020-01-01 14:08:48 +0530429 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 +0000430 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 -0400431 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000432 logger.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400433 "Meter": meterConfig})
434 return nil
435}
436
npujarec5762e2020-01-01 14:08:48 +0530437func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000438
439 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
440
441 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000442 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 +0000443 }
444
Girish Kumar2ad402b2020-03-20 19:45:12 +0000445 logger.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": sq.direction, "TrafficScheds": TrafficSched})
npujarec5762e2020-01-01 14:08:48 +0530446 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000447 IntfId: sq.intfID, OnuId: sq.onuID,
448 UniId: sq.uniID, PortNo: sq.uniPort,
449 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000450 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000451 }
452
453 // On receiving the CreateTrafficQueues request, the driver should create corresponding
454 // downstream queues.
Girish Kumar2ad402b2020-03-20 19:45:12 +0000455 logger.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": sq.direction, "TrafficQueues": trafficQueues})
npujarec5762e2020-01-01 14:08:48 +0530456 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000457 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
458 UniId: sq.uniID, PortNo: sq.uniPort,
459 TrafficQueues: trafficQueues}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000460 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"TrafficQueues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000461 }
462
Esin Karamanccb714b2019-11-29 15:02:06 +0000463 if sq.direction == tp_pb.Direction_DOWNSTREAM {
464 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(sq.tpInst)
465 if len(multicastTrafficQueues) > 0 {
466 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
467 //assumed that there is only one queue per PON for the multicast service
468 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
469 //just put it in interfaceToMcastQueueMap to use for building group members
470 multicastQueuePerPonPort := multicastTrafficQueues[0]
471 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
472 gemPortID: multicastQueuePerPonPort.GemportId,
473 servicePriority: multicastQueuePerPonPort.Priority,
474 }
475 //also store the queue info in kv store
npujarec5762e2020-01-01 14:08:48 +0530476 f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID,
Esin Karamanccb714b2019-11-29 15:02:06 +0000477 multicastQueuePerPonPort.GemportId,
478 multicastQueuePerPonPort.Priority)
479 }
480 }
481 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000482 return nil
483}
484
salmansiddiqui7ac62132019-08-22 03:58:50 +0000485// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530486func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400487
488 var Direction string
489 var SchedCfg *tp_pb.SchedulerConfig
490 var err error
Girish Kumar2ad402b2020-03-20 19:45:12 +0000491 logger.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": sq.direction, "IntfID": sq.intfID,
Gamze Abakafee36392019-10-03 11:17:24 +0000492 "OnuID": sq.onuID, "UniID": sq.uniID, "UniPort": sq.uniPort})
493 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000494 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400495 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000496 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000497 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400498 Direction = "downstream"
499 }
500
Girish Kumar8f73fe02019-12-09 13:19:37 +0000501 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000502 return olterrors.NewErrNotFound("scheduler-config", log.Fields{"IntID": sq.intfID, "Direction": sq.direction}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000503 }
504
npujarec5762e2020-01-01 14:08:48 +0530505 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400506 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000507 return olterrors.NewErrNotFound("meter", log.Fields{"onuID": sq.onuID}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400508 }
509 if KVStoreMeter == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000510 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 -0400511 return nil
512 }
513 cir := KVStoreMeter.Bands[0].Rate
514 cbs := KVStoreMeter.Bands[0].BurstSize
515 eir := KVStoreMeter.Bands[1].Rate
516 ebs := KVStoreMeter.Bands[1].BurstSize
517 pir := cir + eir
518 pbs := cbs + ebs
519
520 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
521
Gamze Abakafee36392019-10-03 11:17:24 +0000522 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Girish Kumar8f73fe02019-12-09 13:19:37 +0000523
524 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
525 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000526 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 +0000527 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400528
npujarec5762e2020-01-01 14:08:48 +0530529 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000530 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
531 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400532 TrafficQueues: TrafficQueues}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000533 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
534 log.Fields{"intfID": sq.intfID, "TrafficQueues": TrafficQueues}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400535 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000536 logger.Debug("Removed traffic queues successfully")
npujarec5762e2020-01-01 14:08:48 +0530537 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000538 IntfId: sq.intfID, OnuId: sq.onuID,
539 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400540 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000541 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
542 log.Fields{"intfID": sq.intfID, "TrafficSchedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400543 }
544
Girish Kumar2ad402b2020-03-20 19:45:12 +0000545 logger.Debug("Removed traffic schedulers successfully")
salmansiddiqui7ac62132019-08-22 03:58:50 +0000546
547 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400548 * delete the meter id on the KV store.
549 */
npujarec5762e2020-01-01 14:08:48 +0530550 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400551 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000552 return olterrors.NewErrAdapter("unable-to-remove-meter", log.Fields{"onu": sq.onuID, "meter": KVStoreMeter.MeterId}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400553 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000554 logger.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400555 return err
556}
557
Gamze Abakafee36392019-10-03 11:17:24 +0000558// This function allocates tconts and GEM ports for an ONU
npujarec5762e2020-01-01 14:08:48 +0530559func (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 +0000560 var allocIDs []uint32
561 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530562 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530563 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000564 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000565
npujarec5762e2020-01-01 14:08:48 +0530566 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
567 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400568
569 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530570
Girish Kumar2ad402b2020-03-20 19:45:12 +0000571 logger.Infow("creating-new-tcont-and-gem", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
Girish Gowdra54934262019-11-13 14:19:55 +0530572
Manikkaraj kb1d51442019-07-23 10:41:02 -0400573 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530574 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000575 if techProfileInstance == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000576 logger.Infow("tp-instance-not-found--creating-new", log.Fields{"path": tpPath})
npujarec5762e2020-01-01 14:08:48 +0530577 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000578 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530579 // This should not happen, something wrong in KV backend transaction
Girish Kumar2ad402b2020-03-20 19:45:12 +0000580 logger.Errorw("tp-instance-create-failed", log.Fields{"error": err, "tpID": TpID})
Gamze Abakafee36392019-10-03 11:17:24 +0000581 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530582 }
npujarec5762e2020-01-01 14:08:48 +0530583 f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530584 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000585 logger.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
Girish Gowdra3d633032019-12-10 16:37:05 +0530586 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530587 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400588 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000589 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
590 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530591 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000592 logger.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000593 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400594 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530595 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400596 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000597 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
598 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530599 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000600 logger.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000601 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400602 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530603 }
Gamze Abakafee36392019-10-03 11:17:24 +0000604
605 allocID := techProfileInstance.UsScheduler.AllocID
Gamze Abakafee36392019-10-03 11:17:24 +0000606 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Gamze Abakafee36392019-10-03 11:17:24 +0000607 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400608 }
Gamze Abakafee36392019-10-03 11:17:24 +0000609
Girish Gowdra3d633032019-12-10 16:37:05 +0530610 if tpInstanceExists {
611 return allocID, gemPortIDs, techProfileInstance
612 }
613
614 allocIDs = appendUnique(allocIDs, allocID)
615 for _, gemPortID := range gemPortIDs {
616 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
617 }
618
Girish Kumar2ad402b2020-03-20 19:45:12 +0000619 logger.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocIDs": allocIDs, "gemports": allgemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530620 // Send Tconts and GEM ports to KV store
npujarec5762e2020-01-01 14:08:48 +0530621 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000622 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530623}
624
npujarec5762e2020-01-01 14:08:48 +0530625func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530626
Girish Kumar2ad402b2020-03-20 19:45:12 +0000627 logger.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700628 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530629 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530630 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000631 logger.Error("Errow while uploading allocID to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530632 }
npujarec5762e2020-01-01 14:08:48 +0530633 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000634 logger.Error("Errow while uploading GEMports to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530635 }
npujarec5762e2020-01-01 14:08:48 +0530636 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000637 logger.Error("Errow while uploading gemtopon map to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530638 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000639 logger.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400640 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530641 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400642 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530643}
644
645func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000646 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530647 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000648 for _, intfID := range techRange.IntfIds {
649 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400650 tpCount++
Girish Kumar2ad402b2020-03-20 19:45:12 +0000651 logger.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530652 }
653 }
654 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400655 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530656 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800657 "reason": "TP count does not match number of PON ports",
658 "tech-profile-count": tpCount,
Girish Kumarf26e4882020-03-05 06:49:10 +0000659 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts()}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530660 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000661 logger.Infow("Populated techprofile for ponports successfully",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400662 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530663 return nil
664}
665
npujarec5762e2020-01-01 14:08:48 +0530666func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530667 portNo uint32, uplinkClassifier map[string]interface{},
668 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800669 allocID uint32, gemportID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700670 uplinkClassifier[PacketTagType] = SingleTag
Girish Kumar2ad402b2020-03-20 19:45:12 +0000671 logger.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800672 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700673 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530674 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530675}
676
npujarec5762e2020-01-01 14:08:48 +0530677func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530678 portNo uint32, downlinkClassifier map[string]interface{},
679 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800680 allocID uint32, gemportID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700681 downlinkClassifier[PacketTagType] = DoubleTag
Girish Kumar2ad402b2020-03-20 19:45:12 +0000682 logger.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
Manikkaraj k884c1242019-04-11 16:26:42 +0530683 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400684 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
685 if vlan, exists := downlinkClassifier[VlanVid]; exists {
686 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700687 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400688 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000689 logger.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800690 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400691 }
692 }
693 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530694 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400695
Manikkaraj k884c1242019-04-11 16:26:42 +0530696 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700697 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400698 // vlan_vid is a uint32. must be type asserted as such or conversion fails
699 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530700 if ok {
701 downlinkAction[VlanVid] = dlClVid & 0xfff
702 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530703 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800704 "reason": "failed to convert VLANID classifier",
705 "vlan-id": VlanVid}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530706 }
707
David K. Bainbridge794735f2020-02-11 21:01:37 -0800708 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700709 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530710}
711
npujarec5762e2020-01-01 14:08:48 +0530712func (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 +0530713 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800714 allocID uint32, gemPortID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530715 /* One of the OLT platform (Broadcom BAL) requires that symmetric
716 flows require the same flow_id to be used across UL and DL.
717 Since HSIA flow is the only symmetric flow currently, we need to
718 re-use the flow_id across both direction. The 'flow_category'
719 takes priority over flow_cookie to find any available HSIA_FLOW
720 id for the ONU.
721 */
Girish Kumar2ad402b2020-03-20 19:45:12 +0000722 logger.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700723 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530724 "logicalFlow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530725 var vlanPbit uint32 = 0xff // means no pbit
Manikkaraj kb1d51442019-07-23 10:41:02 -0400726 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000727 vlanPbit = classifier[VlanPcp].(uint32)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000728 logger.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800729 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000730 logger.Debugw("pbit-not-found-in-flow", log.Fields{"vlan-pcp": VlanPcp})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400731 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700732 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530733 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000734 logger.Debug("flow-already-exists")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800735 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530736 }
npujarec5762e2020-01-01 14:08:48 +0530737 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530738 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530739 return olterrors.NewErrNotFound("hsia-flow-id", log.Fields{"direction": direction}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530740 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800741 classifierProto, err := makeOpenOltClassifierField(classifier)
742 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530743 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530744 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000745 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800746 actionProto, err := makeOpenOltActionField(action)
747 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530748 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530749 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000750 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800751 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530752 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530753 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800754 log.Fields{
755 "classifier": classifier,
756 "action": action,
757 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530758 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700759 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
760 OnuId: int32(onuID),
761 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000762 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530763 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700764 AllocId: int32(allocID),
765 NetworkIntfId: int32(networkIntfID),
766 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530767 Classifier: classifierProto,
768 Action: actionProto,
769 Priority: int32(logicalFlow.Priority),
770 Cookie: logicalFlow.Cookie,
771 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800772 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530773 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530774 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000775 logger.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800776 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
777 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
778 flow.OnuId,
779 flow.UniId,
780 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530781 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": flow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800782 }
783 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +0530784}
Esin Karamanae41e2b2019-12-17 18:13:13 +0000785
David K. Bainbridge794735f2020-02-11 21:01:37 -0800786func (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 +0530787
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530788 networkIntfID, err := getNniIntfID(classifier, action)
789 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530790 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800791 "classifier": classifier,
792 "action": action},
793 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530794 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530795
796 // Clear the action map
797 for k := range action {
798 delete(action, k)
799 }
800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700801 action[TrapToHost] = true
802 classifier[UDPSrc] = uint32(68)
803 classifier[UDPDst] = uint32(67)
804 classifier[PacketTagType] = SingleTag
805 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530806
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700807 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530808 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000809 logger.Debug("Flow-exists--not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800810 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530811 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530812
David K. Bainbridge794735f2020-02-11 21:01:37 -0800813 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 +0530814
815 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530816 return olterrors.NewErrNotFound("flow", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800817 "interface-id": intfID,
818 "gem-port": gemPortID,
819 "cookie": flowStoreCookie},
820 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530821 }
822
Girish Kumar2ad402b2020-03-20 19:45:12 +0000823 logger.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530824
David K. Bainbridge794735f2020-02-11 21:01:37 -0800825 classifierProto, err := makeOpenOltClassifierField(classifier)
826 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530827 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530828 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000829 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800830 actionProto, err := makeOpenOltActionField(action)
831 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530832 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530833 }
834
David K. Bainbridge794735f2020-02-11 21:01:37 -0800835 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700836 OnuId: int32(onuID),
837 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530838 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700839 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700840 AllocId: int32(allocID),
841 NetworkIntfId: int32(networkIntfID),
842 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530843 Classifier: classifierProto,
844 Action: actionProto,
845 Priority: int32(logicalFlow.Priority),
846 Cookie: logicalFlow.Cookie,
847 PortNo: portNo}
848
David K. Bainbridge794735f2020-02-11 21:01:37 -0800849 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530850 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800851 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000852 logger.Debug("DHCP UL flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800853 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
854 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
855 dhcpFlow.OnuId,
856 dhcpFlow.UniId,
857 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530858 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId, log.Fields{"flow": dhcpFlow}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530859 }
860
David K. Bainbridge794735f2020-02-11 21:01:37 -0800861 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530862}
863
Esin Karamanae41e2b2019-12-17 18:13:13 +0000864//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +0530865func (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 -0800866 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32) error {
867 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow)
Esin Karamanae41e2b2019-12-17 18:13:13 +0000868}
869
870//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +0530871func (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 -0800872 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +0000873
874 networkIntfID, err := getNniIntfID(classifier, action)
875 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530876 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800877 "classifier": classifier,
878 "action": action},
879 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000880 }
881
882 // Clear the action map
883 for k := range action {
884 delete(action, k)
885 }
886
887 action[TrapToHost] = true
888 classifier[PacketTagType] = SingleTag
889 delete(classifier, VlanVid)
890
891 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530892 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000893 logger.Debug("Flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800894 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +0000895 }
896
npujarec5762e2020-01-01 14:08:48 +0530897 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 +0000898
899 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530900 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800901 "interface-id": intfID,
902 "oni-id": onuID,
903 "cookie": flowStoreCookie,
904 "flow-type": flowType},
905 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000906 }
907
Girish Kumar2ad402b2020-03-20 19:45:12 +0000908 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 +0000909
David K. Bainbridge794735f2020-02-11 21:01:37 -0800910 classifierProto, err := makeOpenOltClassifierField(classifier)
911 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530912 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000913 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000914 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800915 actionProto, err := makeOpenOltActionField(action)
916 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530917 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000918 }
919
David K. Bainbridge794735f2020-02-11 21:01:37 -0800920 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +0000921 OnuId: int32(onuID),
922 UniId: int32(uniID),
923 FlowId: flowID,
924 FlowType: Upstream,
925 AllocId: int32(allocID),
926 NetworkIntfId: int32(networkIntfID),
927 GemportId: int32(gemPortID),
928 Classifier: classifierProto,
929 Action: actionProto,
930 Priority: int32(logicalFlow.Priority),
931 Cookie: logicalFlow.Cookie,
932 PortNo: portNo}
933
David K. Bainbridge794735f2020-02-11 21:01:37 -0800934 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530935 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": flow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800936 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000937 logger.Debugf("%s UL flow added to device successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +0000938
David K. Bainbridge794735f2020-02-11 21:01:37 -0800939 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
940 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
941 flow.OnuId,
942 flow.UniId,
943 flow.FlowId, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530944 return olterrors.NewErrPersistence("update", "flow", flow.FlowId, log.Fields{"flow": flow}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000945 }
946
David K. Bainbridge794735f2020-02-11 21:01:37 -0800947 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +0000948}
949
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700950// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Girish Gowdrafae935c2020-02-17 19:21:44 +0530951func (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 +0000952 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 +0530953
954 uplinkClassifier := make(map[string]interface{})
955 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +0530956
manikkaraj kbf256be2019-03-25 00:13:48 +0530957 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700958 uplinkClassifier[EthType] = uint32(EapEthType)
959 uplinkClassifier[PacketTagType] = SingleTag
960 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530961 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700962 uplinkAction[TrapToHost] = true
963 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530964 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000965 logger.Debug("Flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800966 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530967 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530968 //Add Uplink EAPOL Flow
npujarec5762e2020-01-01 14:08:48 +0530969 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530970 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530971 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800972 "interface-id": intfID,
973 "onu-id": onuID,
974 "coookie": flowStoreCookie},
975 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +0530976 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000977 logger.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530978
David K. Bainbridge794735f2020-02-11 21:01:37 -0800979 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
980 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530981 return olterrors.NewErrInvalidValue(log.Fields{"classifier": uplinkClassifier}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +0530982 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000983 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800984 actionProto, err := makeOpenOltActionField(uplinkAction)
985 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530986 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +0530987 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000988 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800989 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530990 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530991 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800992 "classifier": classifier,
993 "action": action},
994 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530995 }
996
David K. Bainbridge794735f2020-02-11 21:01:37 -0800997 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700998 OnuId: int32(onuID),
999 UniId: int32(uniID),
1000 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001001 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001002 AllocId: int32(allocID),
1003 NetworkIntfId: int32(networkIntfID),
1004 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301005 Classifier: classifierProto,
1006 Action: actionProto,
1007 Priority: int32(logicalFlow.Priority),
1008 Cookie: logicalFlow.Cookie,
1009 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001010 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301011 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001012 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001013 logger.Debug("EAPOL UL flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001014 flowCategory := "EAPOL"
1015 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1016 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1017 upstreamFlow.OnuId,
1018 upstreamFlow.UniId,
1019 upstreamFlow.FlowId,
1020 /* lowCategory, */
1021 flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301022 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId, log.Fields{"flow": upstreamFlow}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301023 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301024
Girish Kumar2ad402b2020-03-20 19:45:12 +00001025 logger.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001026 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301027}
1028
David K. Bainbridge794735f2020-02-11 21:01:37 -08001029func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001030 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001031
1032 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1033 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1034 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001035 if vlanID != ReservedVlan {
1036 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001037 classifier.OVid = vid
1038 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301039 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001040 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1041 vid := uint32(metadata)
1042 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001043 classifier.IVid = vid
1044 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301045 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301046 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001047 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301048 classifier.OPbits = vlanPcp
1049 } else {
1050 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301051 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001052 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1053 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1054 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1055 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001056 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001057 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1058 classifier.PktTagType = pktTagType
1059
1060 switch pktTagType {
1061 case SingleTag:
1062 case DoubleTag:
1063 case Untagged:
1064 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001065 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301066 }
1067 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001068 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301069}
1070
David K. Bainbridge794735f2020-02-11 21:01:37 -08001071func makeOpenOltActionField(actionInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001072 var actionCmd openoltpb2.ActionCmd
1073 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301074 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001075 if _, ok := actionInfo[PopVlan]; ok {
1076 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301077 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001078 } else if _, ok := actionInfo[PushVlan]; ok {
1079 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301080 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001081 } else if _, ok := actionInfo[TrapToHost]; ok {
1082 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301083 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001084 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301085 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001086 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301087}
1088
Manikkaraj kb1d51442019-07-23 10:41:02 -04001089func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
1090 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +05301091}
1092
Gamze Abakafee36392019-10-03 11:17:24 +00001093// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301094func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1095 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001096 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001097 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301098 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001099 olterrors.NewErrAdapter("delete-tech-profile-failed", nil, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301100 // return err
1101 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001102 }
1103 }
1104 return nil
1105}
1106
1107// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301108func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001109 if uniPortName == "" {
1110 uniPortName = fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1111 }
npujarec5762e2020-01-01 14:08:48 +05301112 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001113 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 -04001114 }
1115 return nil
1116}
1117
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001118func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301119 if len(classifier) == 0 { // should never happen
Girish Kumar2ad402b2020-03-20 19:45:12 +00001120 logger.Error("Invalid classfier object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301121 return 0
1122 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001123 logger.Debugw("generating flow store cookie", log.Fields{"classifier": classifier, "gemPortID": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301124 var jsonData []byte
1125 var flowString string
1126 var err error
1127 // TODO: Do we need to marshall ??
1128 if jsonData, err = json.Marshal(classifier); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001129 logger.Error("Failed to encode classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301130 return 0
1131 }
1132 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001133 if gemPortID != 0 {
1134 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301135 }
1136 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001137 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301138 hash := big.NewInt(0)
1139 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301140 generatedHash := hash.Uint64()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001141 logger.Debugw("hash generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301142 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301143}
1144
npujarec5762e2020-01-01 14:08:48 +05301145func (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 +05301146 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001147 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001148 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1149 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1150 */
1151 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001152 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001153 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001154 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001155 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001156 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301157 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001158 if existingFlows != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001159 logger.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001160 //for _, f := range *existingFlows {
1161 // flows = append(flows, f)
1162 //}
1163 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001164 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001165 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 +05301166 return &flows
1167}
1168
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001169//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1170// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1171// var intfId uint32
1172// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1173// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1174// */
1175// if flow.AccessIntfId != -1 {
1176// intfId = uint32(flow.AccessIntfId)
1177// } else {
1178// intfId = uint32(flow.NetworkIntfId)
1179// }
1180// // Get existing flows matching flowid for given subscriber from KV store
1181// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1182// if existingFlows != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001183// logger.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001184// for _, f := range *existingFlows {
1185// flows = append(flows, f)
1186// }
1187// }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001188// 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 -04001189// return &flows
1190//}
1191
npujarec5762e2020-01-01 14:08:48 +05301192func (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 +00001193 logger.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
npujarec5762e2020-01-01 14:08:48 +05301194 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001195 logger.Debug("Error while Storing flow into KV store")
manikkaraj k17652a72019-05-06 09:06:36 -04001196 return err
1197 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001198 logger.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301199 return nil
1200}
1201
David K. Bainbridge794735f2020-02-11 21:01:37 -08001202func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001203
1204 var intfID uint32
1205 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1206 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1207 */
1208 if deviceFlow.AccessIntfId != -1 {
1209 intfID = uint32(deviceFlow.AccessIntfId)
1210 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001211 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001212 intfID = uint32(deviceFlow.NetworkIntfId)
1213 }
1214
Girish Kumar2ad402b2020-03-20 19:45:12 +00001215 logger.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301216 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001217
1218 st, _ := status.FromError(err)
1219 if st.Code() == codes.AlreadyExists {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001220 logger.Debug("Flow already exists", log.Fields{"err": err, "deviceFlow": deviceFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001221 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301222 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001223
1224 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001225 logger.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
npujarec5762e2020-01-01 14:08:48 +05301226 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001227 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001228 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301229 if deviceFlow.GemportId != -1 {
1230 // No need to register the flow if it is a trap on nni flow.
npujarec5762e2020-01-01 14:08:48 +05301231 f.registerFlow(ctx, logicalFlow, deviceFlow)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301232 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001233 logger.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001234 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001235}
1236
David K. Bainbridge794735f2020-02-11 21:01:37 -08001237func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001238 logger.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001239 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1240 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001241 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001242 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 -07001243 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001245 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001246 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001247
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001248 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001249 logger.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001250 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301251}
1252
1253/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1254 //update core flows_proxy : flows_proxy.update('/', flows)
1255}
1256
1257func generateStoredId(flowId uint32, direction string)uint32{
1258
David K. Bainbridge82efc492019-09-04 09:57:11 -07001259 if direction == Upstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001260 logger.Debug("Upstream flow shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301261 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001262 }else if direction == Downstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001263 logger.Debug("Downstream flow not shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301264 return flowId
1265 }else{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001266 logger.Errorw("Unrecognized direction",log.Fields{"direction": direction})
manikkaraj kbf256be2019-03-25 00:13:48 +05301267 return flowId
1268 }
1269}
1270
1271*/
1272
David K. Bainbridge794735f2020-02-11 21:01:37 -08001273func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001274
1275 classifierInfo := make(map[string]interface{})
1276 actionInfo := make(map[string]interface{})
1277
1278 classifierInfo[EthType] = uint32(LldpEthType)
1279 classifierInfo[PacketTagType] = Untagged
1280 actionInfo[TrapToHost] = true
1281
1282 // LLDP flow is installed to trap LLDP packets on the NNI port.
1283 // We manage flow_id resource pool on per PON port basis.
1284 // Since this situation is tricky, as a hack, we pass the NNI port
1285 // index (network_intf_id) as PON port Index for the flow_id resource
1286 // pool. Also, there is no ONU Id available for trapping LLDP packets
1287 // on NNI port, use onu_id as -1 (invalid)
1288 // ****************** CAVEAT *******************
1289 // This logic works if the NNI Port Id falls within the same valid
1290 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1291 // we need to have a re-look at this.
1292 // *********************************************
1293
1294 var onuID = -1
1295 var uniID = -1
1296 var gemPortID = -1
1297
David K. Bainbridge794735f2020-02-11 21:01:37 -08001298 networkInterfaceID, err := IntfIDFromNniPortNum(portNo)
1299 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301300 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001301 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001302 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301303 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001304 logger.Debug("Flow-exists--not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001305 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001306 }
npujarec5762e2020-01-01 14:08:48 +05301307 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001308
1309 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301310 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001311 "interface-id": networkInterfaceID,
1312 "onu-id": onuID,
1313 "uni-id": uniID,
1314 "gem-port-id": gemPortID,
1315 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00001316 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001317 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001318 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1319 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001320 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001321 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001322 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001323 actionProto, err := makeOpenOltActionField(actionInfo)
1324 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001325 return olterrors.NewErrInvalidValue(log.Fields{"action": actionInfo}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001326 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001327 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
Humera Kouser94d7a842019-08-25 19:04:32 -04001328
1329 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1330 OnuId: int32(onuID), // OnuId not required
1331 UniId: int32(uniID), // UniId not used
1332 FlowId: flowID,
1333 FlowType: Downstream,
1334 NetworkIntfId: int32(networkInterfaceID),
1335 GemportId: int32(gemPortID),
1336 Classifier: classifierProto,
1337 Action: actionProto,
1338 Priority: int32(flow.Priority),
1339 Cookie: flow.Cookie,
1340 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001341 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001342 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001343 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001344 logger.Debug("LLDP trap on NNI flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001345 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1346 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1347 int32(onuID),
1348 int32(uniID),
1349 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001350 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001351 }
1352 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301353}
1354
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301355func getUniPortPath(intfID uint32, onuID int32, uniID int32) string {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001356 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1357}
1358
1359//getOnuChildDevice to fetch onu
1360func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001361 logger.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001362 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001363 onuDevice, err := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
1364 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301365 return nil, olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001366 "interface-id": parentPortNo,
1367 "onu-id": onuID},
Girish Kumarf26e4882020-03-05 06:49:10 +00001368 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301369 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001370 logger.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
Manikkaraj k884c1242019-04-11 16:26:42 +05301371 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301372}
1373
1374func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001375 logger.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301376 return nil
1377}
1378
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001379func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001380 logger.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301381}
1382
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001383func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001384 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001385 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001386 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001387 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001388}
1389
Girish Gowdra6b130582019-11-20 16:45:20 +05301390func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1391 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1392 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001393 return olterrors.NewErrNotFound("onu-child-device", log.Fields{"onuId": onuID, "intfID": intfID}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301394 }
1395
1396 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001397 logger.Debugw("sending gem port delete to openonu adapter", log.Fields{"msg": *delGemPortMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301398 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1399 delGemPortMsg,
1400 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
1401 f.deviceHandler.deviceType,
1402 onuDevice.Type,
1403 onuDevice.Id,
1404 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001405 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Girish Gowdra6b130582019-11-20 16:45:20 +05301406 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001407 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301408 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001409 logger.Debugw("success sending del gem port to onu adapter", log.Fields{"msg": delGemPortMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301410 return nil
1411}
1412
1413func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1414 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1415 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001416 return olterrors.NewErrNotFound("onu-child-device", log.Fields{"onuId": onuID, "intfID": intfID}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301417 }
1418
1419 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001420 logger.Debugw("sending tcont delete to openonu adapter", log.Fields{"msg": *delTcontMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301421 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1422 delTcontMsg,
1423 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
1424 f.deviceHandler.deviceType,
1425 onuDevice.Type,
1426 onuDevice.Id,
1427 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001428 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Girish Gowdra6b130582019-11-20 16:45:20 +05301429 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001430 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301431 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001432 logger.Debugw("success sending del tcont to onu adapter", log.Fields{"msg": delTcontMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301433 return nil
1434}
1435
Girish Gowdra3d633032019-12-10 16:37:05 +05301436func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1437 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1438 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1439 if val.(int) > 0 {
1440 pnFlDels := val.(int) - 1
1441 if pnFlDels > 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001442 logger.Debugw("flow delete succeeded, more pending",
Girish Gowdra3d633032019-12-10 16:37:05 +05301443 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1444 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1445 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001446 logger.Debugw("all pending flow deletes handled, removing entry from map",
Girish Gowdra3d633032019-12-10 16:37:05 +05301447 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1448 f.pendingFlowDelete.Delete(pnFlDelKey)
1449 }
1450 }
1451 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001452 logger.Debugw("no pending delete flows found",
Girish Gowdra3d633032019-12-10 16:37:05 +05301453 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1454
1455 }
1456
1457}
1458
Girish Gowdrac3037402020-01-22 20:29:53 +05301459// Once the gemport is released for a given onu, it also has to be cleared from local cache
1460// which was used for deriving the gemport->logicalPortNo during packet-in.
1461// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1462// is conveyed to ONOS during packet-in OF message.
1463func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(intfID uint32, onuID uint32, gemPortID uint32) {
1464 f.lockCache.Lock()
1465 defer f.lockCache.Unlock()
1466 onugem := f.onuGemInfo[intfID]
serkant.uluderya96af4932020-02-20 16:58:48 -08001467 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301468 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001469 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301470 // If the gemport is found, delete it from local cache.
1471 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001472 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1473 onugem[i] = onu
Girish Kumar2ad402b2020-03-20 19:45:12 +00001474 logger.Debugw("removed gemport from local cache",
serkant.uluderya96af4932020-02-20 16:58:48 -08001475 log.Fields{"intfID": intfID, "onuID": onuID, "deletedGemPortID": gemPortID, "gemPorts": onu.GemPorts})
Girish Gowdrac3037402020-01-22 20:29:53 +05301476 break
1477 }
1478 }
1479 break
1480 }
1481 }
1482}
1483
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301484//clearResources clears pon resources in kv store and the device
npujarec5762e2020-01-01 14:08:48 +05301485func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301486 gemPortID int32, flowID uint32, flowDirection string,
1487 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001488
Chaitrashree G S90a17952019-11-14 21:51:21 -05001489 tpID, err := getTpIDFromFlow(flow)
1490 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001491 return olterrors.NewErrNotFound("tpid", log.Fields{"flow": flow, "pon": Intf, "onuID": onuID, "uniID": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001492 }
Gamze Abakafee36392019-10-03 11:17:24 +00001493
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001494 if len(updatedFlows) >= 0 {
1495 // There are still flows referencing the same flow_id.
1496 // So the flow should not be freed yet.
1497 // For ex: Case of HSIA where same flow is shared
1498 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00001499 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
1500 olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": updatedFlows}, err).Log()
1501 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001502 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05301503 // Do this for subscriber flows only (not trap from NNI flows)
1504 if onuID != -1 && uniID != -1 {
1505 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1506 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001507 logger.Debugw("creating entry for pending flow delete",
Girish Gowdra3d633032019-12-10 16:37:05 +05301508 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1509 f.pendingFlowDelete.Store(pnFlDelKey, 1)
1510 } else {
1511 pnFlDels := val.(int) + 1
Girish Kumar2ad402b2020-03-20 19:45:12 +00001512 logger.Debugw("updating flow delete entry",
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 }
1516
1517 defer f.deletePendingFlows(Intf, onuID, uniID)
1518 }
1519
Girish Kumar2ad402b2020-03-20 19:45:12 +00001520 logger.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
npujarec5762e2020-01-01 14:08:48 +05301521 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001522
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301523 uni := getUniPortPath(Intf, onuID, uniID)
1524 tpPath := f.getTPpath(Intf, uni, tpID)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001525 logger.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
npujarec5762e2020-01-01 14:08:48 +05301526 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00001527 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1528 return olterrors.NewErrNotFound("tech-profile-in-kv-store", log.Fields{"tpID": tpID, "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00001529 }
1530
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301531 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001532 if f.isGemPortUsedByAnotherFlow(gemPK) {
1533 flowIDs := f.flowsUsedByGemPort[gemPK]
1534 for i, flowIDinMap := range flowIDs {
1535 if flowIDinMap == flowID {
1536 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301537 // everytime flowsUsedByGemPort cache is updated the same should be updated
1538 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001539 f.flowsUsedByGemPort[gemPK] = flowIDs
npujarec5762e2020-01-01 14:08:48 +05301540 f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00001541 break
1542 }
1543 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001544 logger.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301545 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001546 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001547 logger.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301548 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001549 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1550 // 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 +05301551 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Girish Gowdrac3037402020-01-22 20:29:53 +05301552 f.deleteGemPortFromLocalCache(Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001553 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301554 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1555 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001556 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05301557 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1558 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001559 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05301560 // Delete the gem port on the ONU.
1561 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001562 logger.Errorw("error processing delete gem-port towards onu",
Girish Gowdra6b130582019-11-20 16:45:20 +05301563 log.Fields{"err": err, "pon": Intf, "onuID": onuID, "uniID": uniID, "gemPortId": gemPortID})
1564 }
Gamze Abakafee36392019-10-03 11:17:24 +00001565
npujarec5762e2020-01-01 14:08:48 +05301566 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001567 if !ok {
npujarec5762e2020-01-01 14:08:48 +05301568 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
1569 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1570 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1571 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
1572 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301573 // Delete the TCONT on the ONU.
1574 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001575 logger.Errorw("error processing delete tcont towards onu",
Girish Gowdra6b130582019-11-20 16:45:20 +05301576 log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID, "allocId": techprofileInst.UsScheduler.AllocID})
1577 }
Gamze Abakafee36392019-10-03 11:17:24 +00001578 }
1579 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001580 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301581 return nil
1582}
1583
David K. Bainbridge794735f2020-02-11 21:01:37 -08001584// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301585func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301586
Girish Kumar2ad402b2020-03-20 19:45:12 +00001587 logger.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
Esin Karamanccb714b2019-11-29 15:02:06 +00001588
1589 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05301590 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001591 return
1592 }
1593
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301594 var updatedFlows []rsrcMgr.FlowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301595 classifierInfo := make(map[string]interface{})
1596
1597 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1598 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001599 logger.Error(err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301600 return
1601 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301602
David K. Bainbridge794735f2020-02-11 21:01:37 -08001603 onuID := int32(onu)
1604 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301605
1606 for _, field := range flows.GetOfbFields(flow) {
1607 if field.Type == flows.IP_PROTO {
1608 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001609 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301610 }
1611 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001612 logger.Debugw("Extracted access info from flow to be deleted",
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301613 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1614
1615 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1616 onuID = -1
1617 uniID = -1
Girish Kumar2ad402b2020-03-20 19:45:12 +00001618 logger.Debug("Trap on nni flow set oni, uni to -1")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001619 Intf, err = IntfIDFromNniPortNum(inPort)
1620 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001621 logger.Errorw("invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001622 log.Fields{
1623 "port-number": inPort,
1624 "error": err})
1625 return
1626 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301627 }
npujarec5762e2020-01-01 14:08:48 +05301628 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001629 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05301630 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301631 if flowInfo == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001632 logger.Debugw("No FlowInfo found found in KV store",
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301633 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1634 return
1635 }
1636 updatedFlows = nil
1637 for _, flow := range *flowInfo {
1638 updatedFlows = append(updatedFlows, flow)
1639 }
1640
1641 for i, storedFlow := range updatedFlows {
1642 if flow.Id == storedFlow.LogicalFlowID {
1643 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001644 logger.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001645 // DKB
1646 if err = f.removeFlowFromDevice(&removeFlowMessage); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001647 logger.Errorw("failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001648 return
1649 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001650 logger.Debug("Flow removed from device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001651 //Remove the Flow from FlowInfo
1652 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1653 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1654 flowID, flowDirection, portNum, updatedFlows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001655 logger.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301656 return
1657 }
1658 }
1659 }
1660 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001661}
1662
Esin Karamanccb714b2019-11-29 15:02:06 +00001663//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
1664// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05301665func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00001666 classifierInfo := make(map[string]interface{})
1667 formulateClassifierInfoFromFlow(classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00001668 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00001669
1670 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001671 logger.Warnw("No inPort found. Cannot release resources of the multicast flow.", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001672 return
1673 }
1674
Esin Karamanccb714b2019-11-29 15:02:06 +00001675 var onuID = int32(NoneOnuID)
1676 var uniID = int32(NoneUniID)
1677 var flowID uint32
1678 var updatedFlows []rsrcMgr.FlowInfo
1679
npujarec5762e2020-01-01 14:08:48 +05301680 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001681
1682 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05301683 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001684 if flowInfo == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001685 logger.Debugw("No multicast FlowInfo found in the KV store",
Esin Karamanccb714b2019-11-29 15:02:06 +00001686 log.Fields{"Intf": networkInterfaceID, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1687 continue
1688 }
1689 updatedFlows = nil
1690 for _, flow := range *flowInfo {
1691 updatedFlows = append(updatedFlows, flow)
1692 }
1693 for i, storedFlow := range updatedFlows {
1694 if flow.Id == storedFlow.LogicalFlowID {
1695 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001696 logger.Debugw("Multicast flow to be deleted", log.Fields{"flow": storedFlow})
Esin Karamanccb714b2019-11-29 15:02:06 +00001697 //remove from device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001698 if err := f.removeFlowFromDevice(&removeFlowMessage); err != nil {
1699 // DKB
Girish Kumar2ad402b2020-03-20 19:45:12 +00001700 logger.Errorw("failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001701 log.Fields{
1702 "flow-id": flow.Id,
1703 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001704 return
1705 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001706 logger.Debugw("Multicast flow removed from device successfully", log.Fields{"flowId": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001707 //Remove the Flow from FlowInfo
1708 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05301709 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001710 logger.Error("Failed to delete multicast flow from the KV store", log.Fields{"flow": storedFlow, "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001711 return
1712 }
1713 //release flow id
Girish Kumar2ad402b2020-03-20 19:45:12 +00001714 logger.Debugw("Releasing multicast flow id", log.Fields{"flowId": flowID, "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05301715 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001716 }
1717 }
1718 }
1719}
1720
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001721//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07001722func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001723 logger.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301724 var direction string
1725 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001726
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301727 for _, action := range flows.GetActions(flow) {
1728 if action.Type == flows.OUTPUT {
1729 if out := action.GetOutput(); out != nil {
1730 actionInfo[Output] = out.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001731 logger.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301732 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001733 logger.Error("Invalid output port in action")
Girish Gowdracefae192020-03-19 18:14:10 -07001734 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001735 }
1736 }
1737 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001738
1739 if flows.HasGroup(flow) {
1740 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07001741 f.clearFlowFromResourceManager(ctx, flow, direction)
1742 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00001743 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301744 direction = Upstream
1745 } else {
1746 direction = Downstream
1747 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301748
Girish Gowdracefae192020-03-19 18:14:10 -07001749 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(flow, direction)
1750 if err != nil {
1751 return err
1752 }
1753
1754 userKey := tpLockKey{intfID, onuID, uniID}
1755
1756 // Serialize flow removes on a per subscriber basis
1757 if f.perUserFlowHandleLock.TryLock(userKey) {
1758 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
1759 f.perUserFlowHandleLock.Unlock(userKey)
1760 } else {
1761 // Ideally this should never happen
Girish Kumar2ad402b2020-03-20 19:45:12 +00001762 logger.Errorw("failed to acquire lock to remove flow, flow remove aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001763 return errors.New("failed-to-acquire-per-user-lock")
1764 }
1765
1766 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001767}
1768
Girish Gowdra3d633032019-12-10 16:37:05 +05301769func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
1770 uniID uint32, ch chan bool) {
1771 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1772 for {
1773 select {
1774 case <-time.After(20 * time.Millisecond):
1775 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001776 logger.Debug("pending flow deletes completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05301777 ch <- true
1778 return
1779 }
1780 case <-ctx.Done():
Girish Kumar2ad402b2020-03-20 19:45:12 +00001781 logger.Error("flow delete wait handler routine canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05301782 return
1783 }
1784 }
1785}
1786
Esin Karamanae41e2b2019-12-17 18:13:13 +00001787//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
1788func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
1789 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
1790 if ethType, ok := classifierInfo[EthType]; ok {
1791 if ethType.(uint32) == IPv4EthType {
1792 if ipProto, ok := classifierInfo[IPProto]; ok {
1793 if ipProto.(uint32) == IgmpProto {
1794 return true
1795 }
1796 }
1797 }
1798 }
1799 }
1800 return false
1801