blob: 07469d778e81931f9e1969955c7c9fc709aa2ca1 [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
22 "crypto/md5"
Matteo Scandolo6056e822019-11-13 14:05:29 -080023 "encoding/hex"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "encoding/json"
Girish Gowdracefae192020-03-19 18:14:10 -070025 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053026 "fmt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040027 "math/big"
Girish Gowdrafae935c2020-02-17 19:21:44 +053028 "strings"
William Kurkian740a09c2019-10-23 17:07:38 -040029 "sync"
Girish Gowdra3d633032019-12-10 16:37:05 +053030 "time"
Manikkaraj kb1d51442019-07-23 10:41:02 -040031
Esin Karamanccb714b2019-11-29 15:02:06 +000032 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v3/pkg/log"
34 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080035 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000036 "github.com/opencord/voltha-protos/v3/go/common"
37 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
38 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
39 openoltpb2 "github.com/opencord/voltha-protos/v3/go/openolt"
40 tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
41 "github.com/opencord/voltha-protos/v3/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040042
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040043 //deepcopy "github.com/getlantern/deepcopy"
Girish Gowdra3d633032019-12-10 16:37:05 +053044 "github.com/EagleChen/mapmutex"
Thomas Lee S94109f12020-03-03 16:39:29 +053045 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000046 "google.golang.org/grpc/codes"
47 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053048)
49
50const (
51 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070053 //HsiaFlow flow category
54 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053055
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070056 //EapolFlow flow category
57 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053058
Manikkaraj kb1d51442019-07-23 10:41:02 -040059 //DhcpFlow flow category
60 DhcpFlow = "DHCP_FLOW"
61
Esin Karamanccb714b2019-11-29 15:02:06 +000062 //MulticastFlow flow category
63 MulticastFlow = "MULTICAST_FLOW"
64
Esin Karamanae41e2b2019-12-17 18:13:13 +000065 //IgmpFlow flow category
66 IgmpFlow = "IGMP_FLOW"
67
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068 //IPProtoDhcp flow category
69 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053070
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070071 //IPProtoIgmp flow category
72 IPProtoIgmp = 2
73
74 //EapEthType eapethtype value
75 EapEthType = 0x888e
76 //LldpEthType lldp ethtype value
77 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000078 //IPv4EthType IPv4 ethernet type value
79 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070080
81 //IgmpProto proto value
82 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053083
Andrea Campanella7acc0b92020-02-14 09:20:49 +010084 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
85 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040086
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087 //DefaultMgmtVlan default vlan value
88 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053089
manikkaraj kbf256be2019-03-25 00:13:48 +053090 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070091
David K. Bainbridge82efc492019-09-04 09:57:11 -070092 //Upstream constant
93 Upstream = "upstream"
94 //Downstream constant
95 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000096 //Multicast constant
97 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070098 //PacketTagType constant
99 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700100 //Untagged constant
101 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700102 //SingleTag constant
103 SingleTag = "single_tag"
104 //DoubleTag constant
105 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +0530106
107 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108
109 //EthType constant
110 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +0000111 //EthDst constant
112 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113 //TPID constant
114 TPID = "tpid"
115 //IPProto constant
116 IPProto = "ip_proto"
117 //InPort constant
118 InPort = "in_port"
119 //VlanVid constant
120 VlanVid = "vlan_vid"
121 //VlanPcp constant
122 VlanPcp = "vlan_pcp"
123
124 //UDPDst constant
125 UDPDst = "udp_dst"
126 //UDPSrc constant
127 UDPSrc = "udp_src"
128 //Ipv4Dst constant
129 Ipv4Dst = "ipv4_dst"
130 //Ipv4Src constant
131 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700132 //Metadata constant
133 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700134 //TunnelID constant
135 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700136 //Output constant
137 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000138 //GroupID constant
139 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700140 // Actions
141
142 //PopVlan constant
143 PopVlan = "pop_vlan"
144 //PushVlan constant
145 PushVlan = "push_vlan"
146 //TrapToHost constant
147 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400148 //MaxMeterBand constant
149 MaxMeterBand = 2
150 //VlanPCPMask contant
151 VlanPCPMask = 0xFF
152 //VlanvIDMask constant
153 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000154 //IntfID constant
155 IntfID = "intfId"
156 //OnuID constant
157 OnuID = "onuId"
158 //UniID constant
159 UniID = "uniId"
160 //PortNo constant
161 PortNo = "portNo"
162 //AllocID constant
163 AllocID = "allocId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000164
165 //NoneOnuID constant
166 NoneOnuID = -1
167 //NoneUniID constant
168 NoneUniID = -1
169 //NoneGemPortID constant
170 NoneGemPortID = -1
Girish Gowdrafae935c2020-02-17 19:21:44 +0530171
172 // BinaryStringPrefix is binary string prefix
173 BinaryStringPrefix = "0b"
174 // BinaryBit1 is binary bit 1 expressed as a character
175 BinaryBit1 = '1'
manikkaraj kbf256be2019-03-25 00:13:48 +0530176)
177
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400178type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700179 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400180 gemPort uint32
181}
182
Girish Gowdra3d633032019-12-10 16:37:05 +0530183type pendingFlowDeleteKey struct {
184 intfID uint32
185 onuID uint32
186 uniID uint32
187}
188
189type tpLockKey struct {
190 intfID uint32
191 onuID uint32
192 uniID uint32
193}
194
Gamze Abakafee36392019-10-03 11:17:24 +0000195type schedQueue struct {
196 direction tp_pb.Direction
197 intfID uint32
198 onuID uint32
199 uniID uint32
200 tpID uint32
201 uniPort uint32
202 tpInst *tp.TechProfile
203 meterID uint32
204 flowMetadata *voltha.FlowMetadata
205}
206
Esin Karamanccb714b2019-11-29 15:02:06 +0000207type queueInfoBrief struct {
208 gemPortID uint32
209 servicePriority uint32
210}
211
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700212//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530213type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000214 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000215 deviceHandler *DeviceHandler
216 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000217 onuIdsLock sync.RWMutex
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530218 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
219 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
220 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
221 lockCache sync.RWMutex
Girish Gowdra3d633032019-12-10 16:37:05 +0530222 pendingFlowDelete sync.Map
223 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Esin Karamanccb714b2019-11-29 15:02:06 +0000224 perUserFlowHandleLock *mapmutex.Mutex
225 interfaceToMcastQueueMap map[uint32]*queueInfoBrief /*pon interface -> multicast queue map. Required to assign GEM to a bucket during group population*/
manikkaraj kbf256be2019-03-25 00:13:48 +0530226}
227
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700228//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
npujarec5762e2020-01-01 14:08:48 +0530229func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700230 logger.Infow("Initializing flow manager", log.Fields{"deviceId": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530231 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530232 var err error
233 var idx uint32
234
manikkaraj kbf256be2019-03-25 00:13:48 +0530235 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530236 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000237 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530238 if err = flowMgr.populateTechProfilePerPonPort(); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000239 logger.Errorw("Error while populating tech profile mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530240 return nil
241 }
William Kurkian740a09c2019-10-23 17:07:38 -0400242 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530243 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
244 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
245 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo)
246 ponPorts := rMgr.DevInfo.GetPonPorts()
247 //Load the onugem info cache from kv store on flowmanager start
248 for idx = 0; idx < ponPorts; idx++ {
npujarec5762e2020-01-01 14:08:48 +0530249 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000250 logger.Error("Failed to load onu gem info cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530251 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530252 //Load flowID list per gem map per interface from the kvstore.
npujarec5762e2020-01-01 14:08:48 +0530253 flowMgr.loadFlowIDlistForGem(ctx, idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530254 }
255 flowMgr.lockCache = sync.RWMutex{}
Girish Gowdra3d633032019-12-10 16:37:05 +0530256 flowMgr.pendingFlowDelete = sync.Map{}
Girish Gowdrab77ded92020-04-08 11:45:05 -0700257 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(300, 100000000, 10000000, 1.1, 0.2)
Esin Karamanccb714b2019-11-29 15:02:06 +0000258 flowMgr.interfaceToMcastQueueMap = make(map[uint32]*queueInfoBrief)
259 //load interface to multicast queue map from kv store
npujarec5762e2020-01-01 14:08:48 +0530260 flowMgr.loadInterfaceToMulticastQueueMap(ctx)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000261 logger.Info("Initialization of flow manager success!!")
manikkaraj kbf256be2019-03-25 00:13:48 +0530262 return &flowMgr
263}
264
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700265func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700266 if direction == Upstream {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000267 logger.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700268 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700269 } else if direction == Downstream {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000270 logger.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700271 return uint64(flowID), nil
Esin Karamanccb714b2019-11-29 15:02:06 +0000272 } else if direction == Multicast {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000273 logger.Debug("multicast flow, shifting id")
Esin Karamanccb714b2019-11-29 15:02:06 +0000274 return 0x2<<15 | uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400275 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530276 return 0, olterrors.NewErrInvalidValue(log.Fields{"direction": direction}, nil).Log()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400277 }
278}
279
npujarec5762e2020-01-01 14:08:48 +0530280func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000281 logger.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700282 log.Fields{"device": f.deviceHandler.deviceID})
Gamze Abakafee36392019-10-03 11:17:24 +0000283 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
284 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
285 if !ok {
286 flowIDList = []uint32{deviceFlow.FlowId}
287 }
288 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
289 f.flowsUsedByGemPort[gemPK] = flowIDList
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530290 // update the flowids for a gem to the KVstore
npujarec5762e2020-01-01 14:08:48 +0530291 f.resourceMgr.UpdateFlowIDsForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400292}
293
npujarec5762e2020-01-01 14:08:48 +0530294func (f *OpenOltFlowMgr) divideAndAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000295 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
296 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000297 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530298 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400299 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530300
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700301 logger.Infow("dividing-flow", log.Fields{
302 "deviceId": f.deviceHandler.device.Id,
303 "intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
304 "classifier": classifierInfo,
305 "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400306 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
307 // is because the flow is an NNI flow and there would be no onu resources associated with it
308 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400309 if onuID <= 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000310 logger.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530311 return
312 }
313
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700314 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
315 logger.Debugw("uni-port-path", log.Fields{"uni": uni, "deviceId": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530316
317 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
318 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700319 logger.Debugw("dividing-flow-create-tcont-gem-ports", log.Fields{
320 "deviceId": f.deviceHandler.device.Id,
321 "intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
322 "classifier": classifierInfo,
323 "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
npujarec5762e2020-01-01 14:08:48 +0530324 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530325 if allocID == 0 || gemPorts == nil || TpInst == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000326 logger.Error("alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530327 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
328 return
329 }
330 args := make(map[string]uint32)
331 args[IntfID] = intfID
332 args[OnuID] = onuID
333 args[UniID] = uniID
334 args[PortNo] = portNo
335 args[AllocID] = allocID
336
337 /* Flows can be added specific to gemport if p-bits are received.
338 * If no pbit mentioned then adding flows for all gemports
339 */
npujarec5762e2020-01-01 14:08:48 +0530340 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530341 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
342 } else {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700343 logger.Errorw("failed-to-acquire-per-user-flow-handle-lock",
Girish Gowdra3d633032019-12-10 16:37:05 +0530344 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400345 return
346 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530347}
348
salmansiddiqui7ac62132019-08-22 03:58:50 +0000349// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530350func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400351
Girish Kumar2ad402b2020-03-20 19:45:12 +0000352 logger.Debugw("CreateSchedulerQueues", log.Fields{"Dir": sq.direction, "IntfID": sq.intfID,
Gamze Abakafee36392019-10-03 11:17:24 +0000353 "OnuID": sq.onuID, "UniID": sq.uniID, "TpID": sq.tpID, "MeterID": sq.meterID,
354 "TpInst": sq.tpInst, "flowMetadata": sq.flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400355
Gamze Abakafee36392019-10-03 11:17:24 +0000356 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000357 if err != nil {
358 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400359 }
360
361 /* Lets make a simple assumption that if the meter-id is present on the KV store,
362 * then the scheduler and queues configuration is applied on the OLT device
363 * in the given direction.
364 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000365
Manikkaraj kb1d51442019-07-23 10:41:02 -0400366 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530367 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400368 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000369 return olterrors.NewErrNotFound("meter", log.Fields{"intfId": sq.intfID, "onuId": sq.onuID, "uniId": sq.uniID}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400370 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000371
Manikkaraj kb1d51442019-07-23 10:41:02 -0400372 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000373 if KvStoreMeter.MeterId == sq.meterID {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000374 logger.Debug("Scheduler already created for upstream")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400375 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400376 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530377 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800378 "unsupported": "meter-id",
379 "kv-store-meter-id": KvStoreMeter.MeterId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000380 "meter-id-in-flow": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400381 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000382
Girish Kumar2ad402b2020-03-20 19:45:12 +0000383 logger.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": sq.meterID, "Direction": Direction})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000384
Gamze Abakafee36392019-10-03 11:17:24 +0000385 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000386 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Gamze Abakafee36392019-10-03 11:17:24 +0000387 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000388 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400389 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000390
391 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000392 return olterrors.NewErrNotFound("scheduler-config", log.Fields{"IntfID": sq.intfID, "Direction": sq.direction, "tpInst": sq.tpInst}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000393 }
394
Manikkaraj kb1d51442019-07-23 10:41:02 -0400395 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000396 if sq.flowMetadata != nil {
397 for _, meter := range sq.flowMetadata.Meters {
398 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400399 meterConfig = meter
Girish Kumar2ad402b2020-03-20 19:45:12 +0000400 logger.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401 break
402 }
403 }
404 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000405 logger.Error("Flow-metadata-is-not-present-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400406 }
407 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530408 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800409 "reason": "Could-not-get-meterbands-from-flowMetadata",
410 "flow-metadata": sq.flowMetadata,
Girish Kumarf26e4882020-03-05 06:49:10 +0000411 "meter-id": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400412 } else if len(meterConfig.Bands) < MaxMeterBand {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000413 logger.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": sq.meterID})
Thomas Lee S94109f12020-03-03 16:39:29 +0530414 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800415 "reason": "Invalid-number-of-bands-in-meter",
416 "meterband-count": len(meterConfig.Bands),
417 "metabands": meterConfig.Bands,
Girish Kumarf26e4882020-03-05 06:49:10 +0000418 "meter-id": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400419 }
420 cir := meterConfig.Bands[0].Rate
421 cbs := meterConfig.Bands[0].BurstSize
422 eir := meterConfig.Bands[1].Rate
423 ebs := meterConfig.Bands[1].BurstSize
424 pir := cir + eir
425 pbs := cbs + ebs
426 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
427
Gamze Abakafee36392019-10-03 11:17:24 +0000428 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400429
npujarec5762e2020-01-01 14:08:48 +0530430 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000431 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device", log.Fields{"intfID": sq.intfID, "direction": sq.direction}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 }
433
salmansiddiqui7ac62132019-08-22 03:58:50 +0000434 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400435 * store the meter id on the KV store, for further reference.
436 */
npujarec5762e2020-01-01 14:08:48 +0530437 if err := f.resourceMgr.UpdateMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000438 return olterrors.NewErrAdapter("failed-updating-meter-id", log.Fields{"onu-id": sq.onuID, "meter-id": sq.meterID}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400439 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000440 logger.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400441 "Meter": meterConfig})
442 return nil
443}
444
npujarec5762e2020-01-01 14:08:48 +0530445func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000446
447 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
448
449 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000450 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration", log.Fields{"intfID": sq.intfID, "direction": sq.direction}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000451 }
452
Girish Kumar2ad402b2020-03-20 19:45:12 +0000453 logger.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": sq.direction, "TrafficScheds": TrafficSched})
npujarec5762e2020-01-01 14:08:48 +0530454 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000455 IntfId: sq.intfID, OnuId: sq.onuID,
456 UniId: sq.uniID, PortNo: sq.uniPort,
457 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000458 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000459 }
460
461 // On receiving the CreateTrafficQueues request, the driver should create corresponding
462 // downstream queues.
Girish Kumar2ad402b2020-03-20 19:45:12 +0000463 logger.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": sq.direction, "TrafficQueues": trafficQueues})
npujarec5762e2020-01-01 14:08:48 +0530464 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000465 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
466 UniId: sq.uniID, PortNo: sq.uniPort,
467 TrafficQueues: trafficQueues}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000468 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"TrafficQueues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000469 }
470
Esin Karamanccb714b2019-11-29 15:02:06 +0000471 if sq.direction == tp_pb.Direction_DOWNSTREAM {
472 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(sq.tpInst)
473 if len(multicastTrafficQueues) > 0 {
474 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
475 //assumed that there is only one queue per PON for the multicast service
476 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
477 //just put it in interfaceToMcastQueueMap to use for building group members
478 multicastQueuePerPonPort := multicastTrafficQueues[0]
479 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
480 gemPortID: multicastQueuePerPonPort.GemportId,
481 servicePriority: multicastQueuePerPonPort.Priority,
482 }
483 //also store the queue info in kv store
npujarec5762e2020-01-01 14:08:48 +0530484 f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID,
Esin Karamanccb714b2019-11-29 15:02:06 +0000485 multicastQueuePerPonPort.GemportId,
486 multicastQueuePerPonPort.Priority)
487 }
488 }
489 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000490 return nil
491}
492
salmansiddiqui7ac62132019-08-22 03:58:50 +0000493// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530494func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400495
496 var Direction string
497 var SchedCfg *tp_pb.SchedulerConfig
498 var err error
Girish Kumar2ad402b2020-03-20 19:45:12 +0000499 logger.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": sq.direction, "IntfID": sq.intfID,
Gamze Abakafee36392019-10-03 11:17:24 +0000500 "OnuID": sq.onuID, "UniID": sq.uniID, "UniPort": sq.uniPort})
501 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000502 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000504 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000505 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400506 Direction = "downstream"
507 }
508
Girish Kumar8f73fe02019-12-09 13:19:37 +0000509 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000510 return olterrors.NewErrNotFound("scheduler-config", log.Fields{"IntID": sq.intfID, "Direction": sq.direction}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000511 }
512
npujarec5762e2020-01-01 14:08:48 +0530513 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400514 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000515 return olterrors.NewErrNotFound("meter", log.Fields{"onuID": sq.onuID}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400516 }
517 if KVStoreMeter == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000518 logger.Debugw("No-meter-has-been-installed-yet", log.Fields{"direction": Direction, "IntfID": sq.intfID, "OnuID": sq.onuID, "UniID": sq.uniID})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400519 return nil
520 }
521 cir := KVStoreMeter.Bands[0].Rate
522 cbs := KVStoreMeter.Bands[0].BurstSize
523 eir := KVStoreMeter.Bands[1].Rate
524 ebs := KVStoreMeter.Bands[1].BurstSize
525 pir := cir + eir
526 pbs := cbs + ebs
527
528 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
529
Gamze Abakafee36392019-10-03 11:17:24 +0000530 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Girish Kumar8f73fe02019-12-09 13:19:37 +0000531
532 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
533 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000534 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration", log.Fields{"intfID": sq.intfID, "direction": sq.direction}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000535 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400536
npujarec5762e2020-01-01 14:08:48 +0530537 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000538 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
539 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400540 TrafficQueues: TrafficQueues}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000541 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
542 log.Fields{"intfID": sq.intfID, "TrafficQueues": TrafficQueues}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400543 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000544 logger.Debug("Removed traffic queues successfully")
npujarec5762e2020-01-01 14:08:48 +0530545 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000546 IntfId: sq.intfID, OnuId: sq.onuID,
547 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400548 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000549 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
550 log.Fields{"intfID": sq.intfID, "TrafficSchedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400551 }
552
Girish Kumar2ad402b2020-03-20 19:45:12 +0000553 logger.Debug("Removed traffic schedulers successfully")
salmansiddiqui7ac62132019-08-22 03:58:50 +0000554
555 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400556 * delete the meter id on the KV store.
557 */
npujarec5762e2020-01-01 14:08:48 +0530558 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400559 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000560 return olterrors.NewErrAdapter("unable-to-remove-meter", log.Fields{"onu": sq.onuID, "meter": KVStoreMeter.MeterId}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400561 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000562 logger.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400563 return err
564}
565
Gamze Abakafee36392019-10-03 11:17:24 +0000566// This function allocates tconts and GEM ports for an ONU
npujarec5762e2020-01-01 14:08:48 +0530567func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) (uint32, []uint32, *tp.TechProfile) {
Gamze Abakafee36392019-10-03 11:17:24 +0000568 var allocIDs []uint32
569 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530570 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530571 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000572 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000573
npujarec5762e2020-01-01 14:08:48 +0530574 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
575 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400576
577 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530578
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700579 logger.Infow("creating-new-tcont-and-gem", log.Fields{
580 "pon": intfID, "onu": onuID, "uni": uniID,
581 "deviceId": f.deviceHandler.device.Id, "tpId": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530582
Manikkaraj kb1d51442019-07-23 10:41:02 -0400583 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530584 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000585 if techProfileInstance == nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700586 logger.Infow("tp-instance-not-found--creating-new", log.Fields{"path": tpPath, "deviceId": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530587 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000588 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530589 // This should not happen, something wrong in KV backend transaction
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700590 logger.Errorw("tp-instance-create-failed", log.Fields{"error": err, "tpID": TpID, "deviceId": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000591 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530592 }
npujarec5762e2020-01-01 14:08:48 +0530593 f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530594 } else {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700595 logger.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni, "deviceId": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530596 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530597 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400598 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000599 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
600 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530601 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700602 logger.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID, "deviceId": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000603 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400604 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530605 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400606 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000607 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
608 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530609 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700610 logger.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID, "deviceId": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000611 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400612 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530613 }
Gamze Abakafee36392019-10-03 11:17:24 +0000614
615 allocID := techProfileInstance.UsScheduler.AllocID
Gamze Abakafee36392019-10-03 11:17:24 +0000616 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Gamze Abakafee36392019-10-03 11:17:24 +0000617 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400618 }
Gamze Abakafee36392019-10-03 11:17:24 +0000619
Girish Gowdra3d633032019-12-10 16:37:05 +0530620 if tpInstanceExists {
621 return allocID, gemPortIDs, techProfileInstance
622 }
623
624 allocIDs = appendUnique(allocIDs, allocID)
625 for _, gemPortID := range gemPortIDs {
626 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
627 }
628
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700629 logger.Debugw("allocated-tcont-and-GEM-ports", log.Fields{"allocIDs": allocIDs, "gemports": allgemPortIDs, "deviceId": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530630 // Send Tconts and GEM ports to KV store
npujarec5762e2020-01-01 14:08:48 +0530631 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000632 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530633}
634
npujarec5762e2020-01-01 14:08:48 +0530635func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530636
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700637 logger.Debugw("storing-allocated-Tconts-and-GEM-ports-into-KV-store",
638 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs, "deviceId": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530639 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530640 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000641 logger.Error("Errow while uploading allocID to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530642 }
npujarec5762e2020-01-01 14:08:48 +0530643 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000644 logger.Error("Errow while uploading GEMports to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530645 }
npujarec5762e2020-01-01 14:08:48 +0530646 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000647 logger.Error("Errow while uploading gemtopon map to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530648 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700649 logger.Debugw("stored-tconts-and-GEM-into-KV-store-successfully", log.Fields{"deviceId": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400650 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530651 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400652 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530653}
654
655func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000656 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530657 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000658 for _, intfID := range techRange.IntfIds {
659 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400660 tpCount++
Girish Kumar2ad402b2020-03-20 19:45:12 +0000661 logger.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530662 }
663 }
664 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400665 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530666 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800667 "reason": "TP count does not match number of PON ports",
668 "tech-profile-count": tpCount,
Girish Kumarf26e4882020-03-05 06:49:10 +0000669 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts()}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530670 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000671 logger.Infow("Populated techprofile for ponports successfully",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400672 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530673 return nil
674}
675
npujarec5762e2020-01-01 14:08:48 +0530676func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530677 portNo uint32, uplinkClassifier map[string]interface{},
678 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800679 allocID uint32, gemportID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700680 uplinkClassifier[PacketTagType] = SingleTag
Girish Kumar2ad402b2020-03-20 19:45:12 +0000681 logger.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800682 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700683 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530684 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530685}
686
npujarec5762e2020-01-01 14:08:48 +0530687func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530688 portNo uint32, downlinkClassifier map[string]interface{},
689 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800690 allocID uint32, gemportID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700691 downlinkClassifier[PacketTagType] = DoubleTag
Girish Kumar2ad402b2020-03-20 19:45:12 +0000692 logger.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
Manikkaraj k884c1242019-04-11 16:26:42 +0530693 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400694 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
695 if vlan, exists := downlinkClassifier[VlanVid]; exists {
696 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700697 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400698 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000699 logger.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800700 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400701 }
702 }
703 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530704 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400705
Manikkaraj k884c1242019-04-11 16:26:42 +0530706 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700707 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400708 // vlan_vid is a uint32. must be type asserted as such or conversion fails
709 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530710 if ok {
711 downlinkAction[VlanVid] = dlClVid & 0xfff
712 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530713 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800714 "reason": "failed to convert VLANID classifier",
715 "vlan-id": VlanVid}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530716 }
717
David K. Bainbridge794735f2020-02-11 21:01:37 -0800718 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700719 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530720}
721
npujarec5762e2020-01-01 14:08:48 +0530722func (f *OpenOltFlowMgr) addHSIAFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530723 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800724 allocID uint32, gemPortID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530725 /* One of the OLT platform (Broadcom BAL) requires that symmetric
726 flows require the same flow_id to be used across UL and DL.
727 Since HSIA flow is the only symmetric flow currently, we need to
728 re-use the flow_id across both direction. The 'flow_category'
729 takes priority over flow_cookie to find any available HSIA_FLOW
730 id for the ONU.
731 */
Girish Kumar2ad402b2020-03-20 19:45:12 +0000732 logger.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700733 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530734 "logicalFlow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530735 var vlanPbit uint32 = 0xff // means no pbit
Manikkaraj kb1d51442019-07-23 10:41:02 -0400736 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000737 vlanPbit = classifier[VlanPcp].(uint32)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000738 logger.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800739 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000740 logger.Debugw("pbit-not-found-in-flow", log.Fields{"vlan-pcp": VlanPcp})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400741 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700742 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530743 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000744 logger.Debug("flow-already-exists")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800745 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530746 }
npujarec5762e2020-01-01 14:08:48 +0530747 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530748 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530749 return olterrors.NewErrNotFound("hsia-flow-id", log.Fields{"direction": direction}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530750 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800751 classifierProto, err := makeOpenOltClassifierField(classifier)
752 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530753 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530754 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000755 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800756 actionProto, err := makeOpenOltActionField(action)
757 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530758 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530759 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000760 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800761 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530762 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530763 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800764 log.Fields{
765 "classifier": classifier,
766 "action": action,
767 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530768 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700769 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
770 OnuId: int32(onuID),
771 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000772 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530773 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700774 AllocId: int32(allocID),
775 NetworkIntfId: int32(networkIntfID),
776 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530777 Classifier: classifierProto,
778 Action: actionProto,
779 Priority: int32(logicalFlow.Priority),
780 Cookie: logicalFlow.Cookie,
781 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800782 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530783 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530784 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000785 logger.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800786 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
787 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
788 flow.OnuId,
789 flow.UniId,
790 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530791 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": flow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800792 }
793 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +0530794}
Esin Karamanae41e2b2019-12-17 18:13:13 +0000795
David K. Bainbridge794735f2020-02-11 21:01:37 -0800796func (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 +0530797
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530798 networkIntfID, err := getNniIntfID(classifier, action)
799 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530800 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800801 "classifier": classifier,
802 "action": action},
803 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530804 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530805
806 // Clear the action map
807 for k := range action {
808 delete(action, k)
809 }
810
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700811 action[TrapToHost] = true
812 classifier[UDPSrc] = uint32(68)
813 classifier[UDPDst] = uint32(67)
814 classifier[PacketTagType] = SingleTag
815 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530816
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700817 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530818 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000819 logger.Debug("Flow-exists--not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800820 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530821 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530822
David K. Bainbridge794735f2020-02-11 21:01:37 -0800823 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 +0530824
825 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530826 return olterrors.NewErrNotFound("flow", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800827 "interface-id": intfID,
828 "gem-port": gemPortID,
829 "cookie": flowStoreCookie},
830 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530831 }
832
Girish Kumar2ad402b2020-03-20 19:45:12 +0000833 logger.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530834
David K. Bainbridge794735f2020-02-11 21:01:37 -0800835 classifierProto, err := makeOpenOltClassifierField(classifier)
836 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530837 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530838 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000839 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800840 actionProto, err := makeOpenOltActionField(action)
841 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530842 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530843 }
844
David K. Bainbridge794735f2020-02-11 21:01:37 -0800845 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700846 OnuId: int32(onuID),
847 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530848 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700849 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700850 AllocId: int32(allocID),
851 NetworkIntfId: int32(networkIntfID),
852 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530853 Classifier: classifierProto,
854 Action: actionProto,
855 Priority: int32(logicalFlow.Priority),
856 Cookie: logicalFlow.Cookie,
857 PortNo: portNo}
858
David K. Bainbridge794735f2020-02-11 21:01:37 -0800859 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530860 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800861 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000862 logger.Debug("DHCP UL flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800863 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
864 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
865 dhcpFlow.OnuId,
866 dhcpFlow.UniId,
867 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530868 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId, log.Fields{"flow": dhcpFlow}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530869 }
870
David K. Bainbridge794735f2020-02-11 21:01:37 -0800871 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530872}
873
Esin Karamanae41e2b2019-12-17 18:13:13 +0000874//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +0530875func (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 -0800876 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32) error {
877 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow)
Esin Karamanae41e2b2019-12-17 18:13:13 +0000878}
879
880//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +0530881func (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 -0800882 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +0000883
884 networkIntfID, err := getNniIntfID(classifier, action)
885 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530886 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800887 "classifier": classifier,
888 "action": action},
889 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000890 }
891
892 // Clear the action map
893 for k := range action {
894 delete(action, k)
895 }
896
897 action[TrapToHost] = true
898 classifier[PacketTagType] = SingleTag
899 delete(classifier, VlanVid)
900
901 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530902 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000903 logger.Debug("Flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800904 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +0000905 }
906
npujarec5762e2020-01-01 14:08:48 +0530907 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 +0000908
909 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530910 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800911 "interface-id": intfID,
912 "oni-id": onuID,
913 "cookie": flowStoreCookie,
914 "flow-type": flowType},
915 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000916 }
917
Girish Kumar2ad402b2020-03-20 19:45:12 +0000918 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 +0000919
David K. Bainbridge794735f2020-02-11 21:01:37 -0800920 classifierProto, err := makeOpenOltClassifierField(classifier)
921 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530922 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000923 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000924 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800925 actionProto, err := makeOpenOltActionField(action)
926 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530927 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000928 }
929
David K. Bainbridge794735f2020-02-11 21:01:37 -0800930 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +0000931 OnuId: int32(onuID),
932 UniId: int32(uniID),
933 FlowId: flowID,
934 FlowType: Upstream,
935 AllocId: int32(allocID),
936 NetworkIntfId: int32(networkIntfID),
937 GemportId: int32(gemPortID),
938 Classifier: classifierProto,
939 Action: actionProto,
940 Priority: int32(logicalFlow.Priority),
941 Cookie: logicalFlow.Cookie,
942 PortNo: portNo}
943
David K. Bainbridge794735f2020-02-11 21:01:37 -0800944 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530945 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": flow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800946 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000947 logger.Debugf("%s UL flow added to device successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +0000948
David K. Bainbridge794735f2020-02-11 21:01:37 -0800949 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
950 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
951 flow.OnuId,
952 flow.UniId,
953 flow.FlowId, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530954 return olterrors.NewErrPersistence("update", "flow", flow.FlowId, log.Fields{"flow": flow}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000955 }
956
David K. Bainbridge794735f2020-02-11 21:01:37 -0800957 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +0000958}
959
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700960// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Girish Gowdrafae935c2020-02-17 19:21:44 +0530961func (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 +0000962 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 +0530963
964 uplinkClassifier := make(map[string]interface{})
965 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +0530966
manikkaraj kbf256be2019-03-25 00:13:48 +0530967 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700968 uplinkClassifier[EthType] = uint32(EapEthType)
969 uplinkClassifier[PacketTagType] = SingleTag
970 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530971 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700972 uplinkAction[TrapToHost] = true
973 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530974 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000975 logger.Debug("Flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800976 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530977 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530978 //Add Uplink EAPOL Flow
npujarec5762e2020-01-01 14:08:48 +0530979 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530980 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530981 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800982 "interface-id": intfID,
983 "onu-id": onuID,
984 "coookie": flowStoreCookie},
985 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +0530986 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000987 logger.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530988
David K. Bainbridge794735f2020-02-11 21:01:37 -0800989 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
990 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530991 return olterrors.NewErrInvalidValue(log.Fields{"classifier": uplinkClassifier}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +0530992 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000993 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800994 actionProto, err := makeOpenOltActionField(uplinkAction)
995 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530996 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +0530997 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000998 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800999 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301000 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301001 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001002 "classifier": classifier,
1003 "action": action},
1004 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301005 }
1006
David K. Bainbridge794735f2020-02-11 21:01:37 -08001007 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001008 OnuId: int32(onuID),
1009 UniId: int32(uniID),
1010 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001011 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001012 AllocId: int32(allocID),
1013 NetworkIntfId: int32(networkIntfID),
1014 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301015 Classifier: classifierProto,
1016 Action: actionProto,
1017 Priority: int32(logicalFlow.Priority),
1018 Cookie: logicalFlow.Cookie,
1019 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001020 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301021 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001022 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001023 logger.Debug("EAPOL UL flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001024 flowCategory := "EAPOL"
1025 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1026 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1027 upstreamFlow.OnuId,
1028 upstreamFlow.UniId,
1029 upstreamFlow.FlowId,
1030 /* lowCategory, */
1031 flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301032 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId, log.Fields{"flow": upstreamFlow}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301033 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301034
Girish Kumar2ad402b2020-03-20 19:45:12 +00001035 logger.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001036 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301037}
1038
David K. Bainbridge794735f2020-02-11 21:01:37 -08001039func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001040 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001041
1042 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1043 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1044 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001045 if vlanID != ReservedVlan {
1046 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001047 classifier.OVid = vid
1048 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301049 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001050 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1051 vid := uint32(metadata)
1052 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001053 classifier.IVid = vid
1054 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301055 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301056 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001057 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301058 classifier.OPbits = vlanPcp
1059 } else {
1060 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301061 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001062 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1063 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1064 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1065 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001066 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001067 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1068 classifier.PktTagType = pktTagType
1069
1070 switch pktTagType {
1071 case SingleTag:
1072 case DoubleTag:
1073 case Untagged:
1074 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001075 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301076 }
1077 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001078 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301079}
1080
David K. Bainbridge794735f2020-02-11 21:01:37 -08001081func makeOpenOltActionField(actionInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001082 var actionCmd openoltpb2.ActionCmd
1083 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301084 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001085 if _, ok := actionInfo[PopVlan]; ok {
1086 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301087 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001088 } else if _, ok := actionInfo[PushVlan]; ok {
1089 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301090 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001091 } else if _, ok := actionInfo[TrapToHost]; ok {
1092 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301093 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001094 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301095 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001096 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301097}
1098
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001099// getTPpath return the ETCD path for a given UNI port
1100func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uniPath string, TpID uint32) string {
1101 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301102}
1103
Gamze Abakafee36392019-10-03 11:17:24 +00001104// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301105func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1106 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001107 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1108
Gamze Abakafee36392019-10-03 11:17:24 +00001109 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301110 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001111 olterrors.NewErrAdapter("delete-tech-profile-failed", nil, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301112 // return err
1113 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001114 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001115 log.Debugw("tech-profile-deleted", log.Fields{"deviceId": f.deviceHandler.device.Id, "tp": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001116 }
1117 return nil
1118}
1119
1120// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301121func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001122 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001123 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001124 }
npujarec5762e2020-01-01 14:08:48 +05301125 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001126 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 -04001127 }
1128 return nil
1129}
1130
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001131func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301132 if len(classifier) == 0 { // should never happen
Girish Kumar2ad402b2020-03-20 19:45:12 +00001133 logger.Error("Invalid classfier object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301134 return 0
1135 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001136 logger.Debugw("generating flow store cookie", log.Fields{"classifier": classifier, "gemPortID": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301137 var jsonData []byte
1138 var flowString string
1139 var err error
1140 // TODO: Do we need to marshall ??
1141 if jsonData, err = json.Marshal(classifier); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001142 logger.Error("Failed to encode classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301143 return 0
1144 }
1145 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001146 if gemPortID != 0 {
1147 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301148 }
1149 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001150 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301151 hash := big.NewInt(0)
1152 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301153 generatedHash := hash.Uint64()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001154 logger.Debugw("hash generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301155 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301156}
1157
npujarec5762e2020-01-01 14:08:48 +05301158func (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 +05301159 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001160 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001161 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1162 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1163 */
1164 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001165 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001166 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001167 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001168 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001169 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301170 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001171 if existingFlows != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001172 logger.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001173 //for _, f := range *existingFlows {
1174 // flows = append(flows, f)
1175 //}
1176 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001177 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001178 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 +05301179 return &flows
1180}
1181
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001182//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1183// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1184// var intfId uint32
1185// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1186// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1187// */
1188// if flow.AccessIntfId != -1 {
1189// intfId = uint32(flow.AccessIntfId)
1190// } else {
1191// intfId = uint32(flow.NetworkIntfId)
1192// }
1193// // Get existing flows matching flowid for given subscriber from KV store
1194// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1195// if existingFlows != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001196// logger.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001197// for _, f := range *existingFlows {
1198// flows = append(flows, f)
1199// }
1200// }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001201// 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 -04001202// return &flows
1203//}
1204
npujarec5762e2020-01-01 14:08:48 +05301205func (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 +00001206 logger.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
npujarec5762e2020-01-01 14:08:48 +05301207 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001208 logger.Debug("Error while Storing flow into KV store")
manikkaraj k17652a72019-05-06 09:06:36 -04001209 return err
1210 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001211 logger.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301212 return nil
1213}
1214
David K. Bainbridge794735f2020-02-11 21:01:37 -08001215func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001216
1217 var intfID uint32
1218 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1219 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1220 */
1221 if deviceFlow.AccessIntfId != -1 {
1222 intfID = uint32(deviceFlow.AccessIntfId)
1223 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001224 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001225 intfID = uint32(deviceFlow.NetworkIntfId)
1226 }
1227
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001228 logger.Debugw("sending-flow-to-device-via-grpc", log.Fields{
1229 "flow": *deviceFlow,
1230 "deviceId": f.deviceHandler.device.Id,
1231 })
manikkaraj kbf256be2019-03-25 00:13:48 +05301232 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001233
1234 st, _ := status.FromError(err)
1235 if st.Code() == codes.AlreadyExists {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001236 logger.Debug("flow-already-exists", log.Fields{
1237 "err": err,
1238 "deviceFlow": deviceFlow,
1239 "deviceId": f.deviceHandler.device.Id,
1240 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001241 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301242 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001243
1244 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001245 logger.Errorw("failed-to-Add-flow-to-device", log.Fields{
1246 "err": err,
1247 "deviceFlow": deviceFlow,
1248 "deviceId": f.deviceHandler.device.Id,
1249 })
npujarec5762e2020-01-01 14:08:48 +05301250 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001251 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001252 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301253 if deviceFlow.GemportId != -1 {
1254 // No need to register the flow if it is a trap on nni flow.
npujarec5762e2020-01-01 14:08:48 +05301255 f.registerFlow(ctx, logicalFlow, deviceFlow)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301256 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001257 logger.Debugw("flow-added-to-device-successfully", log.Fields{
1258 "flow": *deviceFlow,
1259 "deviceId": f.deviceHandler.device.Id,
1260 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001261 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001262}
1263
David K. Bainbridge794735f2020-02-11 21:01:37 -08001264func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001265 logger.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001266 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1267 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001268 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001269 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 -07001270 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001271 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001272 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001273 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001274
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001275 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001276 logger.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001277 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301278}
1279
1280/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1281 //update core flows_proxy : flows_proxy.update('/', flows)
1282}
1283
1284func generateStoredId(flowId uint32, direction string)uint32{
1285
David K. Bainbridge82efc492019-09-04 09:57:11 -07001286 if direction == Upstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001287 logger.Debug("Upstream flow shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301288 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001289 }else if direction == Downstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001290 logger.Debug("Downstream flow not shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301291 return flowId
1292 }else{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001293 logger.Errorw("Unrecognized direction",log.Fields{"direction": direction})
manikkaraj kbf256be2019-03-25 00:13:48 +05301294 return flowId
1295 }
1296}
1297
1298*/
1299
David K. Bainbridge794735f2020-02-11 21:01:37 -08001300func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001301
1302 classifierInfo := make(map[string]interface{})
1303 actionInfo := make(map[string]interface{})
1304
1305 classifierInfo[EthType] = uint32(LldpEthType)
1306 classifierInfo[PacketTagType] = Untagged
1307 actionInfo[TrapToHost] = true
1308
1309 // LLDP flow is installed to trap LLDP packets on the NNI port.
1310 // We manage flow_id resource pool on per PON port basis.
1311 // Since this situation is tricky, as a hack, we pass the NNI port
1312 // index (network_intf_id) as PON port Index for the flow_id resource
1313 // pool. Also, there is no ONU Id available for trapping LLDP packets
1314 // on NNI port, use onu_id as -1 (invalid)
1315 // ****************** CAVEAT *******************
1316 // This logic works if the NNI Port Id falls within the same valid
1317 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1318 // we need to have a re-look at this.
1319 // *********************************************
1320
1321 var onuID = -1
1322 var uniID = -1
1323 var gemPortID = -1
1324
David K. Bainbridge794735f2020-02-11 21:01:37 -08001325 networkInterfaceID, err := IntfIDFromNniPortNum(portNo)
1326 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301327 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001328 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001329 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301330 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001331 logger.Debug("Flow-exists--not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001332 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001333 }
npujarec5762e2020-01-01 14:08:48 +05301334 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001335
1336 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301337 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001338 "interface-id": networkInterfaceID,
1339 "onu-id": onuID,
1340 "uni-id": uniID,
1341 "gem-port-id": gemPortID,
1342 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00001343 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001344 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001345 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1346 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001347 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001348 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001349 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001350 actionProto, err := makeOpenOltActionField(actionInfo)
1351 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001352 return olterrors.NewErrInvalidValue(log.Fields{"action": actionInfo}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001353 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001354 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
Humera Kouser94d7a842019-08-25 19:04:32 -04001355
1356 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1357 OnuId: int32(onuID), // OnuId not required
1358 UniId: int32(uniID), // UniId not used
1359 FlowId: flowID,
1360 FlowType: Downstream,
1361 NetworkIntfId: int32(networkInterfaceID),
1362 GemportId: int32(gemPortID),
1363 Classifier: classifierProto,
1364 Action: actionProto,
1365 Priority: int32(flow.Priority),
1366 Cookie: flow.Cookie,
1367 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001368 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001369 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001370 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001371 logger.Debug("LLDP trap on NNI flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001372 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1373 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1374 int32(onuID),
1375 int32(uniID),
1376 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001377 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001378 }
1379 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301380}
1381
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001382func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1383 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001384}
1385
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001386//getOnuDevice to fetch onu from cache or core.
1387func (f *OpenOltFlowMgr) getOnuDevice(intfID uint32, onuID uint32) (*OnuDevice, error) {
1388 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1389 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1390 if !ok {
1391 logger.Debugw("couldnt-find-onu-in-cache", log.Fields{"intfID": intfID, "onuID": onuID})
1392 onuDevice, err := f.getChildDevice(intfID, onuID)
1393 if err != nil {
1394 return nil, olterrors.NewErrNotFound("onu-child-device", log.Fields{"onuId": onuID, "intfID": intfID}, err)
1395 }
1396 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1397 //better to ad the device to cache here.
1398 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1399 } else {
1400 logger.Debugw("Found-onu-in-cache", log.Fields{"intfID": intfID, "onuID": onuID})
1401 }
1402
1403 return onuDev.(*OnuDevice), nil
1404}
1405
1406//getChildDevice to fetch onu
1407func (f *OpenOltFlowMgr) getChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001408 logger.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001409 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001410 onuDevice, err := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
1411 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301412 return nil, olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001413 "interface-id": parentPortNo,
1414 "onu-id": onuID},
Girish Kumarf26e4882020-03-05 06:49:10 +00001415 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301416 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001417 logger.Debugw("Successfully received child device from core", log.Fields{"child_device_id": onuDevice.Id, "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301418 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301419}
1420
1421func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001422 logger.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301423 return nil
1424}
1425
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001426func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001427 logger.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301428}
1429
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001430func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001431 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001432 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001433 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001434 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001435}
1436
Girish Gowdra6b130582019-11-20 16:45:20 +05301437func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001438 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301439 if err != nil {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001440 logger.Debugw("couldnt-find-onu-child-device", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1441 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301442 }
1443
1444 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001445 logger.Debugw("sending gem port delete to openonu adapter", log.Fields{"msg": *delGemPortMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301446 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1447 delGemPortMsg,
1448 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
1449 f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001450 onuDev.deviceType,
1451 onuDev.deviceID,
1452 onuDev.proxyDeviceID, ""); sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001453 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001454 "toAdapter": onuDev.deviceType, "onuId": onuDev.deviceID,
1455 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301456 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001457 logger.Debugw("success sending del gem port to onu adapter", log.Fields{"msg": delGemPortMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301458 return nil
1459}
1460
1461func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001462 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301463 if err != nil {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001464 logger.Debugw("couldnt-find-onu-child-device", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1465 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301466 }
1467
1468 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001469 logger.Debugw("sending tcont delete to openonu adapter", log.Fields{"msg": *delTcontMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301470 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1471 delTcontMsg,
1472 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
1473 f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001474 onuDev.deviceType,
1475 onuDev.deviceID,
1476 onuDev.proxyDeviceID, ""); sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001477 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001478 "toAdapter": onuDev.deviceType, "onuId": onuDev.deviceID,
1479 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301480 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001481 logger.Debugw("success sending del tcont to onu adapter", log.Fields{"msg": delTcontMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301482 return nil
1483}
1484
Girish Gowdra3d633032019-12-10 16:37:05 +05301485func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1486 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1487 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1488 if val.(int) > 0 {
1489 pnFlDels := val.(int) - 1
1490 if pnFlDels > 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001491 logger.Debugw("flow delete succeeded, more pending",
Girish Gowdra3d633032019-12-10 16:37:05 +05301492 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1493 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1494 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001495 logger.Debugw("all pending flow deletes handled, removing entry from map",
Girish Gowdra3d633032019-12-10 16:37:05 +05301496 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1497 f.pendingFlowDelete.Delete(pnFlDelKey)
1498 }
1499 }
1500 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001501 logger.Debugw("no pending delete flows found",
Girish Gowdra3d633032019-12-10 16:37:05 +05301502 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1503
1504 }
1505
1506}
1507
Girish Gowdrac3037402020-01-22 20:29:53 +05301508// Once the gemport is released for a given onu, it also has to be cleared from local cache
1509// which was used for deriving the gemport->logicalPortNo during packet-in.
1510// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1511// is conveyed to ONOS during packet-in OF message.
1512func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(intfID uint32, onuID uint32, gemPortID uint32) {
1513 f.lockCache.Lock()
1514 defer f.lockCache.Unlock()
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001515 logger.Debugw("deleting-gem-from-local-cache",
1516 log.Fields{"gem": gemPortID, "intf": intfID, "onu": onuID, "deviceId": f.deviceHandler.device.Id, "onuGem": f.onuGemInfo[intfID]})
Girish Gowdrac3037402020-01-22 20:29:53 +05301517 onugem := f.onuGemInfo[intfID]
serkant.uluderya96af4932020-02-20 16:58:48 -08001518 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301519 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001520 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301521 // If the gemport is found, delete it from local cache.
1522 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001523 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1524 onugem[i] = onu
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001525 logger.Debugw("removed-gemport-from-local-cache",
1526 log.Fields{"intfID": intfID, "onuID": onuID, "deletedGemPortID": gemPortID, "gemPorts": onu.GemPorts, "deviceId": f.deviceHandler.device.Id})
Girish Gowdrac3037402020-01-22 20:29:53 +05301527 break
1528 }
1529 }
1530 break
1531 }
1532 }
1533}
1534
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301535//clearResources clears pon resources in kv store and the device
npujarec5762e2020-01-01 14:08:48 +05301536func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301537 gemPortID int32, flowID uint32, flowDirection string,
1538 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001539
Chaitrashree G S90a17952019-11-14 21:51:21 -05001540 tpID, err := getTpIDFromFlow(flow)
1541 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001542 return olterrors.NewErrNotFound("tpid", log.Fields{"flow": flow, "pon": Intf, "onuID": onuID, "uniID": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001543 }
Gamze Abakafee36392019-10-03 11:17:24 +00001544
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001545 if len(updatedFlows) >= 0 {
1546 // There are still flows referencing the same flow_id.
1547 // So the flow should not be freed yet.
1548 // For ex: Case of HSIA where same flow is shared
1549 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00001550 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
1551 olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": updatedFlows}, err).Log()
1552 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001553 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05301554 // Do this for subscriber flows only (not trap from NNI flows)
1555 if onuID != -1 && uniID != -1 {
1556 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1557 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001558 logger.Debugw("creating entry for pending flow delete",
Girish Gowdra3d633032019-12-10 16:37:05 +05301559 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1560 f.pendingFlowDelete.Store(pnFlDelKey, 1)
1561 } else {
1562 pnFlDels := val.(int) + 1
Girish Kumar2ad402b2020-03-20 19:45:12 +00001563 logger.Debugw("updating flow delete entry",
Girish Gowdra3d633032019-12-10 16:37:05 +05301564 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1565 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1566 }
1567
1568 defer f.deletePendingFlows(Intf, onuID, uniID)
1569 }
1570
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001571 logger.Debugw("releasing-flow-id-to-resource-manager", log.Fields{
1572 "Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID,
1573 "deviceId": f.deviceHandler.device.Id,
1574 })
npujarec5762e2020-01-01 14:08:48 +05301575 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001576
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001577 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301578 tpPath := f.getTPpath(Intf, uni, tpID)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001579 logger.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
npujarec5762e2020-01-01 14:08:48 +05301580 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00001581 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1582 return olterrors.NewErrNotFound("tech-profile-in-kv-store", log.Fields{"tpID": tpID, "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00001583 }
1584
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301585 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001586 if f.isGemPortUsedByAnotherFlow(gemPK) {
1587 flowIDs := f.flowsUsedByGemPort[gemPK]
1588 for i, flowIDinMap := range flowIDs {
1589 if flowIDinMap == flowID {
1590 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301591 // everytime flowsUsedByGemPort cache is updated the same should be updated
1592 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001593 f.flowsUsedByGemPort[gemPK] = flowIDs
npujarec5762e2020-01-01 14:08:48 +05301594 f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00001595 break
1596 }
1597 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001598 logger.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301599 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001600 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001601 logger.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301602 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001603 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1604 // 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 +05301605 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Girish Gowdrac3037402020-01-22 20:29:53 +05301606 f.deleteGemPortFromLocalCache(Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001607 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301608 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1609 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001610 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05301611 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1612 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001613 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05301614 // Delete the gem port on the ONU.
1615 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001616 logger.Errorw("error processing delete gem-port towards onu",
Girish Gowdra6b130582019-11-20 16:45:20 +05301617 log.Fields{"err": err, "pon": Intf, "onuID": onuID, "uniID": uniID, "gemPortId": gemPortID})
1618 }
Gamze Abakafee36392019-10-03 11:17:24 +00001619
npujarec5762e2020-01-01 14:08:48 +05301620 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001621 if !ok {
npujarec5762e2020-01-01 14:08:48 +05301622 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
1623 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1624 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1625 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
1626 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301627 // Delete the TCONT on the ONU.
1628 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001629 logger.Errorw("error processing delete tcont towards onu",
Girish Gowdra6b130582019-11-20 16:45:20 +05301630 log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID, "allocId": techprofileInst.UsScheduler.AllocID})
1631 }
Gamze Abakafee36392019-10-03 11:17:24 +00001632 }
1633 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001634 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301635 return nil
1636}
1637
David K. Bainbridge794735f2020-02-11 21:01:37 -08001638// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301639func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301640
Girish Kumar2ad402b2020-03-20 19:45:12 +00001641 logger.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
Esin Karamanccb714b2019-11-29 15:02:06 +00001642
1643 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05301644 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001645 return
1646 }
1647
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301648 var updatedFlows []rsrcMgr.FlowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301649 classifierInfo := make(map[string]interface{})
1650
1651 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1652 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001653 logger.Error(err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301654 return
1655 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301656
David K. Bainbridge794735f2020-02-11 21:01:37 -08001657 onuID := int32(onu)
1658 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301659
1660 for _, field := range flows.GetOfbFields(flow) {
1661 if field.Type == flows.IP_PROTO {
1662 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001663 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301664 }
1665 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001666 logger.Debugw("Extracted access info from flow to be deleted",
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301667 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1668
1669 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1670 onuID = -1
1671 uniID = -1
Girish Kumar2ad402b2020-03-20 19:45:12 +00001672 logger.Debug("Trap on nni flow set oni, uni to -1")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001673 Intf, err = IntfIDFromNniPortNum(inPort)
1674 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001675 logger.Errorw("invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001676 log.Fields{
1677 "port-number": inPort,
1678 "error": err})
1679 return
1680 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301681 }
npujarec5762e2020-01-01 14:08:48 +05301682 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001683 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05301684 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301685 if flowInfo == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001686 logger.Debugw("No FlowInfo found found in KV store",
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301687 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1688 return
1689 }
1690 updatedFlows = nil
1691 for _, flow := range *flowInfo {
1692 updatedFlows = append(updatedFlows, flow)
1693 }
1694
1695 for i, storedFlow := range updatedFlows {
1696 if flow.Id == storedFlow.LogicalFlowID {
1697 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001698 logger.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001699 // DKB
1700 if err = f.removeFlowFromDevice(&removeFlowMessage); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001701 logger.Errorw("failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001702 return
1703 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001704 logger.Debug("Flow removed from device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001705 //Remove the Flow from FlowInfo
1706 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1707 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1708 flowID, flowDirection, portNum, updatedFlows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001709 logger.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301710 return
1711 }
1712 }
1713 }
1714 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001715}
1716
Esin Karamanccb714b2019-11-29 15:02:06 +00001717//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
1718// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05301719func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00001720 classifierInfo := make(map[string]interface{})
1721 formulateClassifierInfoFromFlow(classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00001722 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00001723
1724 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001725 logger.Warnw("No inPort found. Cannot release resources of the multicast flow.", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001726 return
1727 }
1728
Esin Karamanccb714b2019-11-29 15:02:06 +00001729 var onuID = int32(NoneOnuID)
1730 var uniID = int32(NoneUniID)
1731 var flowID uint32
1732 var updatedFlows []rsrcMgr.FlowInfo
1733
npujarec5762e2020-01-01 14:08:48 +05301734 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001735
1736 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05301737 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001738 if flowInfo == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001739 logger.Debugw("No multicast FlowInfo found in the KV store",
Esin Karamanccb714b2019-11-29 15:02:06 +00001740 log.Fields{"Intf": networkInterfaceID, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1741 continue
1742 }
1743 updatedFlows = nil
1744 for _, flow := range *flowInfo {
1745 updatedFlows = append(updatedFlows, flow)
1746 }
1747 for i, storedFlow := range updatedFlows {
1748 if flow.Id == storedFlow.LogicalFlowID {
1749 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001750 logger.Debugw("Multicast flow to be deleted", log.Fields{"flow": storedFlow})
Esin Karamanccb714b2019-11-29 15:02:06 +00001751 //remove from device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001752 if err := f.removeFlowFromDevice(&removeFlowMessage); err != nil {
1753 // DKB
Girish Kumar2ad402b2020-03-20 19:45:12 +00001754 logger.Errorw("failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001755 log.Fields{
1756 "flow-id": flow.Id,
1757 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001758 return
1759 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001760 logger.Debugw("Multicast flow removed from device successfully", log.Fields{"flowId": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001761 //Remove the Flow from FlowInfo
1762 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05301763 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001764 logger.Error("Failed to delete multicast flow from the KV store", log.Fields{"flow": storedFlow, "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001765 return
1766 }
1767 //release flow id
Girish Kumar2ad402b2020-03-20 19:45:12 +00001768 logger.Debugw("Releasing multicast flow id", log.Fields{"flowId": flowID, "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05301769 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001770 }
1771 }
1772 }
1773}
1774
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001775//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07001776func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001777 logger.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301778 var direction string
1779 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001780
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301781 for _, action := range flows.GetActions(flow) {
1782 if action.Type == flows.OUTPUT {
1783 if out := action.GetOutput(); out != nil {
1784 actionInfo[Output] = out.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001785 logger.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301786 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001787 logger.Error("Invalid output port in action")
Girish Gowdracefae192020-03-19 18:14:10 -07001788 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001789 }
1790 }
1791 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001792
1793 if flows.HasGroup(flow) {
1794 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07001795 f.clearFlowFromResourceManager(ctx, flow, direction)
1796 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00001797 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301798 direction = Upstream
1799 } else {
1800 direction = Downstream
1801 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301802
Girish Gowdracefae192020-03-19 18:14:10 -07001803 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(flow, direction)
1804 if err != nil {
1805 return err
1806 }
1807
1808 userKey := tpLockKey{intfID, onuID, uniID}
1809
1810 // Serialize flow removes on a per subscriber basis
1811 if f.perUserFlowHandleLock.TryLock(userKey) {
1812 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
1813 f.perUserFlowHandleLock.Unlock(userKey)
1814 } else {
1815 // Ideally this should never happen
Girish Kumar2ad402b2020-03-20 19:45:12 +00001816 logger.Errorw("failed to acquire lock to remove flow, flow remove aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001817 return errors.New("failed-to-acquire-per-user-lock")
1818 }
1819
1820 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001821}
1822
Girish Gowdra3d633032019-12-10 16:37:05 +05301823func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
1824 uniID uint32, ch chan bool) {
1825 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1826 for {
1827 select {
1828 case <-time.After(20 * time.Millisecond):
1829 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001830 logger.Debug("pending flow deletes completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05301831 ch <- true
1832 return
1833 }
1834 case <-ctx.Done():
Girish Kumar2ad402b2020-03-20 19:45:12 +00001835 logger.Error("flow delete wait handler routine canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05301836 return
1837 }
1838 }
1839}
1840
Esin Karamanae41e2b2019-12-17 18:13:13 +00001841//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
1842func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
1843 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
1844 if ethType, ok := classifierInfo[EthType]; ok {
1845 if ethType.(uint32) == IPv4EthType {
1846 if ipProto, ok := classifierInfo[IPProto]; ok {
1847 if ipProto.(uint32) == IgmpProto {
1848 return true
1849 }
1850 }
1851 }
1852 }
1853 }
1854 return false
1855}
1856
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001857// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301858// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01001859func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001860 classifierInfo := make(map[string]interface{})
1861 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001862 var UsMeterID uint32
1863 var DsMeterID uint32
1864
Girish Kumar2ad402b2020-03-20 19:45:12 +00001865 logger.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001866 formulateClassifierInfoFromFlow(classifierInfo, flow)
1867
1868 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1869 if err != nil {
1870 // Error logging is already done in the called function
1871 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001872 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301873 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001874
Esin Karamanccb714b2019-11-29 15:02:06 +00001875 if flows.HasGroup(flow) {
1876 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01001877 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001878 }
1879
manikkaraj k17652a72019-05-06 09:06:36 -04001880 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001881 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1882 if err != nil {
1883 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01001884 return err
manikkaraj k17652a72019-05-06 09:06:36 -04001885 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001886
Girish Kumar2ad402b2020-03-20 19:45:12 +00001887 logger.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001888 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001889
Humera Kouser94d7a842019-08-25 19:04:32 -04001890 if ethType, ok := classifierInfo[EthType]; ok {
1891 if ethType.(uint32) == LldpEthType {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001892 logger.Info("Adding LLDP flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01001893 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04001894 }
1895 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001896 if ipProto, ok := classifierInfo[IPProto]; ok {
1897 if ipProto.(uint32) == IPProtoDhcp {
1898 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301899 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001900 logger.Debug("trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01001901 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001902 }
1903 }
1904 }
1905 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001906 if isIgmpTrapDownstreamFlow(classifierInfo) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001907 logger.Debug("trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01001908 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001909 }
A R Karthick1f85b802019-10-11 05:06:05 +00001910
1911 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
npujarec5762e2020-01-01 14:08:48 +05301912 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001913
Chaitrashree G S90a17952019-11-14 21:51:21 -05001914 TpID, err := getTpIDFromFlow(flow)
1915 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001916 return olterrors.NewErrNotFound("tpid-for-flow", log.Fields{"flow": flow, "pon": IntfID, "onuID": onuID, "uniID": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001917 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001918 logger.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001919 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001920 UsMeterID = flows.GetMeterIdFromFlow(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001921 logger.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001922 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001923 DsMeterID = flows.GetMeterIdFromFlow(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001924 logger.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001925
1926 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301927
1928 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1929 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001930 logger.Debugw("no pending flows found, going ahead with flow install", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
npujarec5762e2020-01-01 14:08:48 +05301931 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05301932 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05301933 pendingFlowDelComplete := make(chan bool)
1934 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
1935 select {
1936 case <-pendingFlowDelComplete:
Girish Kumar2ad402b2020-03-20 19:45:12 +00001937 logger.Debugw("all pending flow deletes completed", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
npujarec5762e2020-01-01 14:08:48 +05301938 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05301939
1940 case <-time.After(10 * time.Second):
Girish Kumarf26e4882020-03-05 06:49:10 +00001941 return olterrors.NewErrTimeout("pending-flow-deletes", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID}, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +05301942 }
1943 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001944 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001945}
1946
Esin Karamanccb714b2019-11-29 15:02:06 +00001947// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08001948func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00001949 classifierInfo[PacketTagType] = DoubleTag
Girish Kumar2ad402b2020-03-20 19:45:12 +00001950 logger.Debugw("add-multicast-flow", log.Fields{"classifierInfo": classifierInfo, "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00001951
Esin Karaman65409d82020-03-18 10:58:18 +00001952 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00001953 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001954 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00001955 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00001956 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
1957 //otherwise, classification is based on ipv4_dst by default.
1958 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
1959 mcastFlowClassificationByEthDst := false
1960
1961 if mcastFlowClassificationByEthDst {
1962 //replace ipDst with ethDst
1963 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
1964 flows.IsMulticastIp(ipv4Dst.(uint32)) {
1965 // replace ipv4_dst classifier with eth_dst
1966 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
1967 delete(classifierInfo, Ipv4Dst)
1968 classifierInfo[EthDst] = multicastMac
Girish Kumar2ad402b2020-03-20 19:45:12 +00001969 logger.Debugw("multicast-ip-to-mac-conversion-success", log.Fields{"ip:": ipv4Dst.(uint32), "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00001970 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001971 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00001972 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00001973
David K. Bainbridge794735f2020-02-11 21:01:37 -08001974 onuID := NoneOnuID
1975 uniID := NoneUniID
1976 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00001977
David K. Bainbridge794735f2020-02-11 21:01:37 -08001978 flowStoreCookie := getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301979 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001980 logger.Debugw("multicast-flow-exists-not-re-adding", log.Fields{"classifierInfo": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001981 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00001982 }
npujarec5762e2020-01-01 14:08:48 +05301983 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00001984 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301985 return olterrors.NewErrNotFound("multicast-flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001986 "interface-id": networkInterfaceID,
1987 "onu-id": onuID,
1988 "uni-id": uniID,
1989 "gem-port-id": gemPortID,
1990 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00001991 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00001992 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001993 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1994 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001995 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00001996 }
1997 groupID := actionInfo[GroupID].(uint32)
1998 multicastFlow := openoltpb2.Flow{
1999 FlowId: flowID,
2000 FlowType: Multicast,
2001 NetworkIntfId: int32(networkInterfaceID),
2002 GroupId: groupID,
2003 Classifier: classifierProto,
2004 Priority: int32(flow.Priority),
2005 Cookie: flow.Cookie}
2006
David K. Bainbridge794735f2020-02-11 21:01:37 -08002007 if err = f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002008 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002009 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002010 logger.Debug("multicast flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002011 //get cached group
2012 group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true)
2013 if err == nil {
2014 //calling groupAdd to set group members after multicast flow creation
Andrea Campanellac63bba92020-03-10 17:01:04 +01002015 if err = f.ModifyGroup(ctx, group); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002016 //cached group can be removed now
2017 f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002018 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002019 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002020 }
2021 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002022
2023 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2024 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2025 int32(onuID),
2026 int32(uniID),
2027 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002028 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002029 }
2030 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002031}
2032
Esin Karaman65409d82020-03-18 10:58:18 +00002033//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2034func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2035 if inPort, ok := classifierInfo[InPort]; ok {
2036 nniInterfaceID, err := IntfIDFromNniPortNum(inPort.(uint32))
2037 if err != nil {
2038 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2039 }
2040 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002041 }
Esin Karaman65409d82020-03-18 10:58:18 +00002042 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302043 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002044 if e == nil && len(nniPorts) > 0 {
2045 return nniPorts[0], nil
2046 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302047 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002048}
2049
2050// AddGroup add or update the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002051func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002052 logger.Infow("add-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002053 if group == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002054 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002055 }
2056
2057 groupToOlt := openoltpb2.Group{
2058 GroupId: group.Desc.GroupId,
2059 Command: openoltpb2.Group_SET_MEMBERS,
2060 Action: f.buildGroupAction(),
2061 }
2062
Girish Kumar2ad402b2020-03-20 19:45:12 +00002063 logger.Debugw("Sending group to device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05302064 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002065 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002066 return olterrors.NewErrAdapter("add-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002067 }
2068 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05302069 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002070 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002071 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002072 logger.Debugw("add-group operation performed on the device successfully ", log.Fields{"groupToOlt": groupToOlt})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002073 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002074}
2075
2076//buildGroupAction creates and returns a group action
2077func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2078 var actionCmd openoltpb2.ActionCmd
2079 var action openoltpb2.Action
2080 action.Cmd = &actionCmd
2081 //pop outer vlan
2082 action.Cmd.RemoveOuterTag = true
2083 return &action
2084}
2085
2086// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002087func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002088 logger.Infow("modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002089 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002090 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002091 }
2092
Andrea Campanellac63bba92020-03-10 17:01:04 +01002093 newGroup := f.buildGroup(group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002094 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302095 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002096
2097 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002098 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002099 }
2100
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002101 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002102 if groupExists {
2103 // group already exists
2104 current = f.buildGroup(group.Desc.GroupId, val.Desc.GetBuckets())
Girish Kumar2ad402b2020-03-20 19:45:12 +00002105 logger.Debugw("modify-group: group exists.", log.Fields{"group on the device": val, "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002106 } else {
2107 current = f.buildGroup(group.Desc.GroupId, nil)
2108 }
2109
Girish Kumar2ad402b2020-03-20 19:45:12 +00002110 logger.Debugw("modify-group: comparing current and new.", log.Fields{"group on the device": current, "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002111 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002112 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002113 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002114 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002115
Girish Kumar2ad402b2020-03-20 19:45:12 +00002116 logger.Infow("modify-group -> differences found", log.Fields{"membersToBeAdded": membersToBeAdded,
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002117 "membersToBeRemoved": membersToBeRemoved, "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002118
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002119 groupToOlt := openoltpb2.Group{
2120 GroupId: group.Desc.GroupId,
2121 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002122 var errAdd, errRemoved error
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002123 if membersToBeAdded != nil && len(membersToBeAdded) > 0 {
2124 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2125 groupToOlt.Members = membersToBeAdded
2126 //execute addMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002127 errAdd = f.callGroupAddRemove(&groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002128 }
2129 if membersToBeRemoved != nil && len(membersToBeRemoved) > 0 {
2130 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2131 groupToOlt.Members = membersToBeRemoved
2132 //execute removeMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002133 errRemoved = f.callGroupAddRemove(&groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002134 }
2135
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002136 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002137 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302138 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002139 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002140 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002141 logger.Debugw("modify-group was success. Storing the group", log.Fields{"group": group, "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002142 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002143 logger.Warnw("One of the group add/remove operations has failed. Cannot save group modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002144 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002145 if errAdd != nil {
2146 return errAdd
2147 }
2148 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002149 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002150 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002151}
2152
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002153//callGroupAddRemove performs add/remove buckets operation for the indicated group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002154func (f *OpenOltFlowMgr) callGroupAddRemove(group *openoltpb2.Group) error {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002155 if err := f.performGroupOperation(group); err != nil {
2156 st, _ := status.FromError(err)
2157 //ignore already exists error code
2158 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002159 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002160 }
2161 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002162 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002163}
2164
2165//findDiff compares group members and finds members which only exists in groups2
2166func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2167 var members []*openoltpb2.GroupMember
2168 for _, bucket := range group2.Members {
2169 if !f.contains(group1.Members, bucket) {
2170 // bucket does not exist and must be added
2171 members = append(members, bucket)
2172 }
2173 }
2174 return members
2175}
2176
2177//contains returns true if the members list contains the given member; false otherwise
2178func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2179 for _, groupMember := range members {
2180 if groupMember.InterfaceId == member.InterfaceId {
2181 return true
2182 }
2183 }
2184 return false
2185}
2186
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002187//performGroupOperation call performGroupOperation operation of openolt proto
2188func (f *OpenOltFlowMgr) performGroupOperation(group *openoltpb2.Group) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002189 logger.Debugw("Sending group to device", log.Fields{"groupToOlt": group, "command": group.Command})
Esin Karamanccb714b2019-11-29 15:02:06 +00002190 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2191 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002192 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002193 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002194 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002195}
2196
2197//buildGroup build openoltpb2.Group from given group id and bucket list
2198func (f *OpenOltFlowMgr) buildGroup(groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
2199 group := openoltpb2.Group{
2200 GroupId: groupID}
2201 // create members of the group
2202 if buckets != nil {
2203 for _, ofBucket := range buckets {
2204 member := f.buildMember(ofBucket)
2205 if member != nil && !f.contains(group.Members, member) {
2206 group.Members = append(group.Members, member)
2207 }
2208 }
2209 }
2210 return &group
2211}
2212
2213//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
2214func (f *OpenOltFlowMgr) buildMember(ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
2215 var outPort uint32
2216 outPortFound := false
2217 for _, ofAction := range ofBucket.Actions {
2218 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2219 outPort = ofAction.GetOutput().Port
2220 outPortFound = true
2221 }
2222 }
2223
2224 if !outPortFound {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002225 logger.Debugw("bucket skipped since no out port found in it",
Esin Karamanccb714b2019-11-29 15:02:06 +00002226 log.Fields{"ofBucket": ofBucket})
2227 return nil
2228 }
2229 interfaceID := IntfIDFromUniPortNum(outPort)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002230 logger.Debugw("got associated interface id of the port", log.Fields{"portNumber:": outPort, "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002231 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2232 member := openoltpb2.GroupMember{
2233 InterfaceId: interfaceID,
2234 InterfaceType: openoltpb2.GroupMember_PON,
2235 GemPortId: groupInfo.gemPortID,
2236 Priority: groupInfo.servicePriority,
2237 }
2238 //add member to the group
2239 return &member
2240 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002241 logger.Warnf("bucket skipped since interface-2-gem mapping cannot be found",
Esin Karamanccb714b2019-11-29 15:02:06 +00002242 log.Fields{"ofBucket": ofBucket})
2243 return nil
2244}
2245
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002246//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04002247func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002248
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002249 onuDev, err := f.getOnuDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302250 if err != nil {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002251 logger.Errorw("couldnt-find-onu-child-device", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
2252 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302253 }
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002254 logger.Debugw("Got child device from OLT device handler", log.Fields{"deviceId": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002255
Manikkaraj kb1d51442019-07-23 10:41:02 -04002256 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002257 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002258 logger.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
manikkaraj k17652a72019-05-06 09:06:36 -04002259 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2260 tpDownloadMsg,
2261 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
2262 f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002263 onuDev.deviceType,
2264 onuDev.deviceID,
2265 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002266 if sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002267 return olterrors.NewErrCommunication("send-techprofile-download-request", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002268 "toAdapter": onuDev.deviceType, "onuId": onuDev.deviceID,
2269 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002270 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002271 logger.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302272 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302273}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002274
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302275//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002276func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302277
2278 f.lockCache.Lock()
2279 defer f.lockCache.Unlock()
2280 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2281 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002282 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002283 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302284 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002285 logger.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "onu": onu, "deviceId": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002286 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002287}
2288
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302289//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302290func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302291 f.lockCache.Lock()
2292 defer f.lockCache.Unlock()
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002293 logger.Debugw("adding-gem-to-onu-info-map",
2294 log.Fields{"gem": gemPort, "intf": intfID, "onu": onuID, "deviceId": f.deviceHandler.device.Id, "onuGem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302295 onugem := f.onuGemInfo[intfID]
2296 // update the gem to the local cache as well as to kv strore
2297 for idx, onu := range onugem {
2298 if onu.OnuID == onuID {
2299 // check if gem already exists , else update the cache and kvstore
2300 for _, gem := range onu.GemPorts {
2301 if gem == gemPort {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002302 logger.Debugw("gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2303 log.Fields{"gem": gemPort, "deviceId": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302304 return
2305 }
2306 }
2307 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2308 f.onuGemInfo[intfID] = onugem
2309 }
2310 }
npujarec5762e2020-01-01 14:08:48 +05302311 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302312 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002313 logger.Errorw("failed-to-add-gem-to-onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort, "deviceId": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002314 return
2315 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002316 logger.Debugw("gem-added-to-onu-info-map",
2317 log.Fields{"gem": gemPort, "intf": intfID, "onu": onuID, "deviceId": f.deviceHandler.device.Id, "onuGem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002318}
2319
2320// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002321
2322//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
2323func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302324
2325 f.lockCache.Lock()
2326 defer f.lockCache.Unlock()
2327
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002328 logger.Debugw("Getting-ONU-ID-from-GEM-port-and-PON-port", log.Fields{
2329 "deviceId": f.deviceHandler.device.Id, "onuGemInfo": f.onuGemInfo[intfID],
2330 "serialNumber": serialNumber, "intfId": intfID, "gemPortId": gemPortID})
2331
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302332 // get onuid from the onugem info cache
2333 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002334
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302335 for _, onu := range onugem {
2336 for _, gem := range onu.GemPorts {
2337 if gem == gemPortID {
2338 return onu.OnuID, nil
2339 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002340 }
2341 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302342 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002343 "serial-number": serialNumber,
2344 "interface-id": intfID,
2345 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00002346 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002347}
2348
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002349//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302350func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002351 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002352 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002353 var err error
2354
2355 if packetIn.IntfType == "pon" {
2356 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002357 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002358 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002359 return logicalPortNum, err
2360 }
2361 if packetIn.PortNo != 0 {
2362 logicalPortNum = packetIn.PortNo
2363 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002364 uniID := uint32(0) // FIXME - multi-uni support
2365 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002366 }
2367 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
npujarec5762e2020-01-01 14:08:48 +05302368 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002369 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002370 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002371 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002372 logger.Debugw("Retrieved logicalport from packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08002373 "logicalPortNum": logicalPortNum,
2374 "IntfType": packetIn.IntfType,
2375 "packet": hex.EncodeToString(packetIn.Pkt),
2376 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002377 return logicalPortNum, nil
2378}
2379
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002380//GetPacketOutGemPortID returns gemPortId
npujarec5762e2020-01-01 14:08:48 +05302381func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002382 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002383 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302384
2385 f.lockCache.Lock()
2386 defer f.lockCache.Unlock()
2387 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
2388
2389 gemPortID, ok := f.packetInGemPort[pktInkey]
2390 if ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002391 logger.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302392 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002393 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302394 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
npujarec5762e2020-01-01 14:08:48 +05302395 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302396 if err == nil {
2397 if gemPortID != 0 {
2398 f.packetInGemPort[pktInkey] = gemPortID
Girish Kumar2ad402b2020-03-20 19:45:12 +00002399 logger.Debugw("Found gem port from kv store and updating cache with gemport",
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302400 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
2401 return gemPortID, nil
2402 }
2403 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002404 return uint32(0), olterrors.NewErrNotFound("gem-port", log.Fields{"pktinkey": pktInkey, "gem": gemPortID}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002405}
2406
npujarec5762e2020-01-01 14:08:48 +05302407func installFlowOnAllGemports(ctx context.Context,
2408 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04002409 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
David K. Bainbridge794735f2020-02-11 21:01:37 -08002410 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32) error,
npujarec5762e2020-01-01 14:08:48 +05302411 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05302412 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302413 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05302414 ) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04002415 args map[string]uint32,
2416 classifier map[string]interface{}, action map[string]interface{},
2417 logicalFlow *ofp.OfpFlowStats,
2418 gemPorts []uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05302419 TpInst *tp.TechProfile,
Manikkaraj kb1d51442019-07-23 10:41:02 -04002420 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00002421 vlanID ...uint32) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002422 logger.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05302423
2424 for _, gemPortAttribute := range TpInst.UpstreamGemPortAttributeList {
2425 var gemPortID uint32
2426 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
2427 // We need to trim prefix "0b", before further processing
2428 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
2429 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
2430 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
2431 // If a particular character in the string is set to '1', identify the index of this character from
2432 // the LSB position which marks the PCP bit consumed by the given gem port.
2433 // This PCP bit now becomes a classifier in the flow.
2434 if pbitSet == BinaryBit1 {
2435 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
2436 gemPortID = gemPortAttribute.GemportID
2437 if FlowType == HsiaFlow || FlowType == DhcpFlow || FlowType == IgmpFlow {
2438 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
2439 } else if FlowType == EapolFlow {
2440 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0])
2441 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002442 logger.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
Girish Gowdrafae935c2020-02-17 19:21:44 +05302443 return
2444 }
2445 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002446 }
2447 }
2448}
2449
David K. Bainbridge794735f2020-02-11 21:01:37 -08002450func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002451 logger.Debug("Adding trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002452 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002453 classifier[PacketTagType] = DoubleTag
2454 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002455 /* We manage flowId resource pool on per PON port basis.
2456 Since this situation is tricky, as a hack, we pass the NNI port
2457 index (network_intf_id) as PON port Index for the flowId resource
2458 pool. Also, there is no ONU Id available for trapping DHCP packets
2459 on NNI port, use onu_id as -1 (invalid)
2460 ****************** CAVEAT *******************
2461 This logic works if the NNI Port Id falls within the same valid
2462 range of PON Port Ids. If this doesn't work for some OLT Vendor
2463 we need to have a re-look at this.
2464 *********************************************
2465 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002466 onuID := -1
2467 uniID := -1
2468 gemPortID := -1
2469 allocID := -1
David K. Bainbridge794735f2020-02-11 21:01:37 -08002470 networkInterfaceID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302471 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302472 return olterrors.NewErrNotFound("nni-intreface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002473 "classifier": classifier,
2474 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002475 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302476 }
2477
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002478 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302479 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002480 logger.Debug("Flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002481 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002482 }
npujarec5762e2020-01-01 14:08:48 +05302483 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002484 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302485 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002486 "interface-id": networkInterfaceID,
2487 "onu-id": onuID,
2488 "uni-id": uniID,
2489 "gem-port-id": gemPortID,
2490 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002491 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002492 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002493 classifierProto, err := makeOpenOltClassifierField(classifier)
2494 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002495 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002496 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002497 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002498 actionProto, err := makeOpenOltActionField(action)
2499 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002500 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002501 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002502 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002503 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2504 OnuId: int32(onuID), // OnuId not required
2505 UniId: int32(uniID), // UniId not used
2506 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002507 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002508 AllocId: int32(allocID), // AllocId not used
2509 NetworkIntfId: int32(networkInterfaceID),
2510 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002511 Classifier: classifierProto,
2512 Action: actionProto,
2513 Priority: int32(logicalFlow.Priority),
2514 Cookie: logicalFlow.Cookie,
2515 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002516 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002517 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002518 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002519 logger.Debug("DHCP trap on NNI flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002520 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
2521 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2522 int32(onuID),
2523 int32(uniID),
2524 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002525 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002526 }
2527 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002528}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002529
Esin Karamanae41e2b2019-12-17 18:13:13 +00002530//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2531func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2532 var packetType string
2533 ovid, ivid := false, false
2534 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2535 vid := vlanID & VlanvIDMask
2536 if vid != ReservedVlan {
2537 ovid = true
2538 }
2539 }
2540 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2541 vid := uint32(metadata)
2542 if vid != ReservedVlan {
2543 ivid = true
2544 }
2545 }
2546 if ovid && ivid {
2547 packetType = DoubleTag
2548 } else if !ovid && !ivid {
2549 packetType = Untagged
2550 } else {
2551 packetType = SingleTag
2552 }
2553 return packetType
2554}
2555
2556//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002557func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002558 logger.Debugw("Adding igmp-trap-of-nni-flow", log.Fields{"classifierInfo": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002559 action := make(map[string]interface{})
2560 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2561 action[TrapToHost] = true
2562 /* We manage flowId resource pool on per PON port basis.
2563 Since this situation is tricky, as a hack, we pass the NNI port
2564 index (network_intf_id) as PON port Index for the flowId resource
2565 pool. Also, there is no ONU Id available for trapping packets
2566 on NNI port, use onu_id as -1 (invalid)
2567 ****************** CAVEAT *******************
2568 This logic works if the NNI Port Id falls within the same valid
2569 range of PON Port Ids. If this doesn't work for some OLT Vendor
2570 we need to have a re-look at this.
2571 *********************************************
2572 */
2573 onuID := -1
2574 uniID := -1
2575 gemPortID := -1
2576 allocID := -1
2577 networkInterfaceID, err := getNniIntfID(classifier, action)
2578 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302579 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002580 "classifier": classifier,
2581 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002582 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002583 }
2584 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302585 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002586 logger.Debug("igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002587 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002588 }
npujarec5762e2020-01-01 14:08:48 +05302589 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002590 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302591 return olterrors.NewErrNotFound("igmp-flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002592 "interface-id": networkInterfaceID,
2593 "onu-id": onuID,
2594 "uni-id": uniID,
2595 "gem-port-id": gemPortID,
2596 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002597 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002598 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002599 classifierProto, err := makeOpenOltClassifierField(classifier)
2600 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002601 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002602 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002603 logger.Debugw("Created classifier proto for the IGMP flow", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002604 actionProto, err := makeOpenOltActionField(action)
2605 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002606 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002607 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002608 logger.Debugw("Created action proto for the IGMP flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002609 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2610 OnuId: int32(onuID), // OnuId not required
2611 UniId: int32(uniID), // UniId not used
2612 FlowId: flowID,
2613 FlowType: Downstream,
2614 AllocId: int32(allocID), // AllocId not used
2615 NetworkIntfId: int32(networkInterfaceID),
2616 GemportId: int32(gemPortID), // GemportId not used
2617 Classifier: classifierProto,
2618 Action: actionProto,
2619 Priority: int32(logicalFlow.Priority),
2620 Cookie: logicalFlow.Cookie,
2621 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002622 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002623 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002624 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002625 logger.Debug("IGMP Trap on NNI flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002626 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
2627 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2628 int32(onuID),
2629 int32(uniID),
2630 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002631 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002632 }
2633 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002634}
2635
salmansiddiqui7ac62132019-08-22 03:58:50 +00002636func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2637 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302638 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002639 }
2640 if Dir == tp_pb.Direction_UPSTREAM {
2641 return "upstream", nil
2642 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2643 return "downstream", nil
2644 }
2645 return "", nil
2646}
2647
npujarec5762e2020-01-01 14:08:48 +05302648func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00002649 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
2650 TpID uint32, uni string) {
2651 var gemPort uint32
2652 intfID := args[IntfID]
2653 onuID := args[OnuID]
2654 uniID := args[UniID]
2655 portNo := args[PortNo]
2656 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00002657 if ipProto, ok := classifierInfo[IPProto]; ok {
2658 if ipProto.(uint32) == IPProtoDhcp {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002659 logger.Info("Adding DHCP flow")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002660 if pcp, ok := classifierInfo[VlanPcp]; ok {
2661 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2662 tp_pb.Direction_UPSTREAM,
2663 pcp.(uint32))
2664 //Adding DHCP upstream flow
npujarec5762e2020-01-01 14:08:48 +05302665 f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002666 } else {
2667 //Adding DHCP upstream flow to all gemports
Girish Gowdrafae935c2020-02-17 19:21:44 +05302668 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002669 }
2670
2671 } else if ipProto == IgmpProto {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002672 logger.Infow("Adding Us IGMP flow", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "classifierInfo:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002673 if pcp, ok := classifierInfo[VlanPcp]; ok {
2674 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2675 tp_pb.Direction_UPSTREAM,
2676 pcp.(uint32))
npujarec5762e2020-01-01 14:08:48 +05302677 f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002678 } else {
2679 //Adding IGMP upstream flow to all gem ports
Girish Gowdrafae935c2020-02-17 19:21:44 +05302680 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002681 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002682 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002683 logger.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002684 return
2685 }
2686 } else if ethType, ok := classifierInfo[EthType]; ok {
2687 if ethType.(uint32) == EapEthType {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002688 logger.Info("Adding EAPOL flow")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002689 var vlanID uint32
2690 if val, ok := classifierInfo[VlanVid]; ok {
2691 vlanID = (val.(uint32)) & VlanvIDMask
2692 } else {
2693 vlanID = DefaultMgmtVlan
2694 }
2695 if pcp, ok := classifierInfo[VlanPcp]; ok {
2696 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2697 tp_pb.Direction_UPSTREAM,
2698 pcp.(uint32))
2699
Girish Gowdrafae935c2020-02-17 19:21:44 +05302700 f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002701 } else {
Girish Gowdrafae935c2020-02-17 19:21:44 +05302702 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002703 }
2704 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002705 } else if _, ok := actionInfo[PushVlan]; ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002706 logger.Info("Adding upstream data rule")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002707 if pcp, ok := classifierInfo[VlanPcp]; ok {
2708 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2709 tp_pb.Direction_UPSTREAM,
2710 pcp.(uint32))
2711 //Adding HSIA upstream flow
npujarec5762e2020-01-01 14:08:48 +05302712 f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002713 } else {
2714 //Adding HSIA upstream flow to all gemports
Girish Gowdrafae935c2020-02-17 19:21:44 +05302715 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002716 }
2717 } else if _, ok := actionInfo[PopVlan]; ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002718 logger.Info("Adding Downstream data rule")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002719 if pcp, ok := classifierInfo[VlanPcp]; ok {
2720 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05002721 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00002722 pcp.(uint32))
2723 //Adding HSIA downstream flow
npujarec5762e2020-01-01 14:08:48 +05302724 f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002725 } else {
2726 //Adding HSIA downstream flow to all gemports
Girish Gowdrafae935c2020-02-17 19:21:44 +05302727 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002728 }
2729 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002730 logger.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002731 return
2732 }
2733 // Send Techprofile download event to child device in go routine as it takes time
2734 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
2735}
2736
Gamze Abakafee36392019-10-03 11:17:24 +00002737func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
2738 flowIDList := f.flowsUsedByGemPort[gemPK]
2739 if len(flowIDList) > 1 {
2740 return true
2741 }
2742 return false
2743}
2744
npujarec5762e2020-01-01 14:08:48 +05302745func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
2746 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002747 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2748 for _, currentGemPort := range currentGemPorts {
2749 for _, tpGemPort := range tpGemPorts {
2750 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2751 return true, currentGemPort
2752 }
2753 }
2754 }
Girish Gowdra54934262019-11-13 14:19:55 +05302755 if tpInst.InstanceCtrl.Onu == "single-instance" {
2756 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
npujarec5762e2020-01-01 14:08:48 +05302757 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID)
2758 f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID)
Girish Gowdra54934262019-11-13 14:19:55 +05302759
2760 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
2761 // still be used on other uni ports.
2762 // So, we need to check and make sure that no other gem port is referring to the given TP ID
2763 // on any other uni port.
npujarec5762e2020-01-01 14:08:48 +05302764 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002765 logger.Debugw("got single instance tp instances", log.Fields{"tpInstances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302766 for i := 0; i < len(tpInstances); i++ {
2767 tpI := tpInstances[i]
2768 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05302769 for _, tpGemPort := range tpGemPorts {
2770 if tpGemPort.GemportID != gemPortID {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002771 logger.Debugw("single instance tp is in use by gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302772 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05302773 }
2774 }
2775 }
2776 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002777 logger.Debug("tech profile is not in use by any gem")
Gamze Abakafee36392019-10-03 11:17:24 +00002778 return false, 0
2779}
2780
salmansiddiqui7ac62132019-08-22 03:58:50 +00002781func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002782 for _, field := range flows.GetOfbFields(flow) {
2783 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002784 classifierInfo[EthType] = field.GetEthType()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002785 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002786 } else if field.Type == flows.ETH_DST {
2787 classifierInfo[EthDst] = field.GetEthDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002788 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002789 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002790 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002791 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002792 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002793 classifierInfo[InPort] = field.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002794 logger.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002795 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302796 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00002797 logger.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002798 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002799 classifierInfo[VlanPcp] = field.GetVlanPcp()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002800 logger.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002801 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002802 classifierInfo[UDPDst] = field.GetUdpDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002803 logger.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002804 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002805 classifierInfo[UDPSrc] = field.GetUdpSrc()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002806 logger.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002807 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002808 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002809 logger.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002810 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002811 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002812 logger.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002813 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002814 classifierInfo[Metadata] = field.GetTableMetadata()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002815 logger.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002816 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002817 classifierInfo[TunnelID] = field.GetTunnelId()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002818 logger.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002819 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002820 logger.Errorw("Un supported field type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002821 return
2822 }
2823 }
2824}
2825
2826func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002827 for _, action := range flows.GetActions(flow) {
2828 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002829 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002830 actionInfo[Output] = out.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002831 logger.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002832 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002833 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002834 }
Scott Baker355d1742019-10-24 10:57:52 -07002835 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002836 actionInfo[PopVlan] = true
Girish Kumar2ad402b2020-03-20 19:45:12 +00002837 logger.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002838 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002839 if out := action.GetPush(); out != nil {
2840 if tpid := out.GetEthertype(); tpid != 0x8100 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002841 logger.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002842 } else {
2843 actionInfo[PushVlan] = true
2844 actionInfo[TPID] = tpid
Girish Kumar2ad402b2020-03-20 19:45:12 +00002845 logger.Debugw("action-type-push-vlan",
salmansiddiqui7ac62132019-08-22 03:58:50 +00002846 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
2847 }
2848 }
Scott Baker355d1742019-10-24 10:57:52 -07002849 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002850 if out := action.GetSetField(); out != nil {
2851 if field := out.GetField(); field != nil {
2852 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00002853 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002854 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002855 /*logger.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
Esin Karamanccb714b2019-11-29 15:02:06 +00002856 formulateSetFieldActionInfoFromFlow(field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002857 }
2858 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002859 } else if action.Type == flows.GROUP {
2860 formulateGroupActionInfoFromFlow(action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002861 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002862 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002863 }
2864 }
2865 return nil
2866}
2867
Esin Karamanccb714b2019-11-29 15:02:06 +00002868func formulateSetFieldActionInfoFromFlow(field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
2869 if ofbField := field.GetOfbField(); ofbField != nil {
2870 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
2871 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2872 actionInfo[VlanVid] = vlan & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00002873 logger.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002874 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002875 logger.Error("No Invalid vlan id in set vlan-vid action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002876 }
2877 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002878 logger.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00002879 }
2880 }
2881}
2882
2883func formulateGroupActionInfoFromFlow(action *ofp.OfpAction, actionInfo map[string]interface{}) {
2884 if action.GetGroup() == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002885 logger.Warn("No group entry found in the group action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002886 } else {
2887 actionInfo[GroupID] = action.GetGroup().GroupId
Girish Kumar2ad402b2020-03-20 19:45:12 +00002888 logger.Debugw("action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002889 }
2890}
2891
salmansiddiqui7ac62132019-08-22 03:58:50 +00002892func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002893 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002894 logger.Debug("Controller bound trap flows, getting inport from tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002895 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2896 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002897 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002898 classifierInfo[InPort] = uniPort
Girish Kumar2ad402b2020-03-20 19:45:12 +00002899 logger.Debugw("upstream pon-to-controller-flow,inport-in-tunnelid", log.Fields{"newInPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002900 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05302901 return olterrors.NewErrNotFound("child-in-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002902 "reason": "upstream pon-to-controller-flow, NO-inport-in-tunnelid",
Girish Kumarf26e4882020-03-05 06:49:10 +00002903 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002904 }
2905 }
2906 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002907 logger.Debug("Non-Controller flows, getting uniport from tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002908 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07002909 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002910 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002911 actionInfo[Output] = uniPort
Girish Kumar2ad402b2020-03-20 19:45:12 +00002912 logger.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid", log.Fields{"newOutPort": actionInfo[Output].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002913 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05302914 return olterrors.NewErrNotFound("out-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002915 "reason": "downstream-nni-to-pon-port-flow, no-outport-in-tunnelid",
Girish Kumarf26e4882020-03-05 06:49:10 +00002916 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002917 }
2918 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2919 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002920 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002921 classifierInfo[InPort] = uniPort
Girish Kumar2ad402b2020-03-20 19:45:12 +00002922 logger.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
David K. Bainbridge82efc492019-09-04 09:57:11 -07002923 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002924 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05302925 return olterrors.NewErrNotFound("nni-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002926 "reason": "upstream-pon-to-nni-port-flow, no-inport-in-tunnelid",
2927 "in-port": classifierInfo[InPort].(uint32),
2928 "out-port": actionInfo[Output].(uint32),
Girish Kumarf26e4882020-03-05 06:49:10 +00002929 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002930 }
2931 }
2932 }
2933 return nil
2934}
Gamze Abakafee36392019-10-03 11:17:24 +00002935
Chaitrashree G S90a17952019-11-14 21:51:21 -05002936func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00002937 /* Metadata 8 bytes:
2938 Most Significant 2 Bytes = Inner VLAN
2939 Next 2 Bytes = Tech Profile ID(TPID)
2940 Least Significant 4 Bytes = Port ID
2941 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
2942 subscriber related flows.
2943 */
2944 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
2945 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00002946 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00002947 }
2948 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002949 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00002950}
2951
2952func appendUnique(slice []uint32, item uint32) []uint32 {
2953 for _, sliceElement := range slice {
2954 if sliceElement == item {
2955 return slice
2956 }
2957 }
2958 return append(slice, item)
2959}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302960
2961// getNniIntfID gets nni intf id from the flow classifier/action
2962func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
2963
2964 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
2965 if portType == voltha.Port_PON_OLT {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002966 intfID, err := IntfIDFromNniPortNum(action[Output].(uint32))
2967 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002968 logger.Debugw("invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002969 log.Fields{
2970 "port-number": action[Output].(uint32),
2971 "error": err})
2972 return uint32(0), err
2973 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002974 logger.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302975 return intfID, nil
2976 } else if portType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002977 intfID, err := IntfIDFromNniPortNum(classifier[InPort].(uint32))
2978 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002979 logger.Debugw("invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002980 log.Fields{
2981 "port-number": action[Output].(uint32),
2982 "error": err})
2983 return uint32(0), err
2984 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002985 logger.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302986 return intfID, nil
2987 }
2988 return uint32(0), nil
2989}
2990
2991// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
npujarec5762e2020-01-01 14:08:48 +05302992func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302993 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
2994
2995 f.lockCache.Lock()
2996 defer f.lockCache.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05002997 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302998 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05002999 if lookupGemPort == gemPort {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003000 logger.Debugw("pktin key/value found in cache , no need to update kv as we are assuming both will be in sync",
Matt Jeanneret1719a072019-12-20 14:50:14 -05003001 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
3002 return
3003 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303004 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003005 f.packetInGemPort[pktInkey] = gemPort
3006
npujarec5762e2020-01-01 14:08:48 +05303007 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Girish Kumar2ad402b2020-03-20 19:45:12 +00003008 logger.Debugw("pktin key not found in local cache or value is different. updating cache and kv store", log.Fields{"pktinkey": pktInkey, "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303009 return
3010}
3011
3012// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303013func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303014
3015 f.lockCache.Lock()
3016 defer f.lockCache.Unlock()
3017 onugem := f.onuGemInfo[intfID]
3018 for idx, onu := range onugem {
3019 if onu.OnuID == onuID {
3020 for _, uni := range onu.UniPorts {
3021 if uni == portNum {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003022 logger.Debugw("uni already in cache, no need to update cache and kv store",
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303023 log.Fields{"uni": portNum})
3024 return
3025 }
3026 }
3027 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3028 f.onuGemInfo[intfID] = onugem
3029 }
3030 }
npujarec5762e2020-01-01 14:08:48 +05303031 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303032}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303033
npujarec5762e2020-01-01 14:08:48 +05303034func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3035 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303036 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003037 logger.Error("Failed to get flowid list per gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303038 return
3039 }
3040 for gem, FlowIDs := range flowIDsList {
3041 gemPK := gemPortKey{intf, uint32(gem)}
3042 f.flowsUsedByGemPort[gemPK] = FlowIDs
3043 }
3044 return
3045}
Esin Karamanccb714b2019-11-29 15:02:06 +00003046
3047//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
3048//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05303049func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
3050 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00003051 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003052 logger.Error("Failed to get pon interface to multicast queue map")
Esin Karamanccb714b2019-11-29 15:02:06 +00003053 return
3054 }
3055 for intf, queueInfo := range storedMulticastQueueMap {
3056 q := queueInfoBrief{
3057 gemPortID: queueInfo[0],
3058 servicePriority: queueInfo[1],
3059 }
3060 f.interfaceToMcastQueueMap[intf] = &q
3061 }
3062}
3063
3064//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
3065//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
3066//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05303067func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
3068 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00003069 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003070 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00003071 }
3072 if exists {
3073 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
3074 }
3075 return nil, exists, nil
3076}
3077
3078func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
3079 groupDesc := ofp.OfpGroupDesc{
3080 Type: ofp.OfpGroupType_OFPGT_ALL,
3081 GroupId: groupID,
3082 }
3083 groupEntry := ofp.OfpGroupEntry{
3084 Desc: &groupDesc,
3085 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003086 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003087 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00003088 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003089 bucket := ofp.OfpBucket{
3090 Actions: acts,
3091 }
3092 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00003093 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003094 return &groupEntry
3095}