blob: e882e185c5a969bae7e5bd0f78ab0b69426320b9 [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
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070017//Package adaptercore provides the utility for olt devices, flows and statistics
manikkaraj kbf256be2019-03-25 00:13:48 +053018package adaptercore
19
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"
25 "errors"
26 "fmt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040027 "math/big"
William Kurkian740a09c2019-10-23 17:07:38 -040028 "sync"
Girish Gowdra3d633032019-12-10 16:37:05 +053029 "time"
Manikkaraj kb1d51442019-07-23 10:41:02 -040030
Esin Karamanccb714b2019-11-29 15:02:06 +000031 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
32 "github.com/opencord/voltha-lib-go/v3/pkg/log"
33 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
Manikkaraj k884c1242019-04-11 16:26:42 +053034 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000035 "github.com/opencord/voltha-protos/v3/go/common"
36 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
37 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
38 openoltpb2 "github.com/opencord/voltha-protos/v3/go/openolt"
39 tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
40 "github.com/opencord/voltha-protos/v3/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040041
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040042 //deepcopy "github.com/getlantern/deepcopy"
Girish Gowdra3d633032019-12-10 16:37:05 +053043 "github.com/EagleChen/mapmutex"
Daniele Rossi22db98e2019-07-11 11:50:00 +000044 "google.golang.org/grpc/codes"
45 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053046)
47
48const (
49 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053050
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070051 //HsiaFlow flow category
52 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053053
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070054 //EapolFlow flow category
55 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053056
Manikkaraj kb1d51442019-07-23 10:41:02 -040057 //DhcpFlow flow category
58 DhcpFlow = "DHCP_FLOW"
59
Esin Karamanccb714b2019-11-29 15:02:06 +000060 //MulticastFlow flow category
61 MulticastFlow = "MULTICAST_FLOW"
62
Esin Karamanae41e2b2019-12-17 18:13:13 +000063 //IgmpFlow flow category
64 IgmpFlow = "IGMP_FLOW"
65
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070066 //IPProtoDhcp flow category
67 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053068
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070069 //IPProtoIgmp flow category
70 IPProtoIgmp = 2
71
72 //EapEthType eapethtype value
73 EapEthType = 0x888e
74 //LldpEthType lldp ethtype value
75 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000076 //IPv4EthType IPv4 ethernet type value
77 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070078
79 //IgmpProto proto value
80 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053081
82 //FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070083
Humera Kouser94d7a842019-08-25 19:04:32 -040084 //ReservedVlan Transparent Vlan
David K. Bainbridge82efc492019-09-04 09:57:11 -070085 ReservedVlan = 4095
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
manikkaraj kbf256be2019-03-25 00:13:48 +0530171)
172
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400173type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700174 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400175 gemPort uint32
176}
177
Girish Gowdra3d633032019-12-10 16:37:05 +0530178type pendingFlowDeleteKey struct {
179 intfID uint32
180 onuID uint32
181 uniID uint32
182}
183
184type tpLockKey struct {
185 intfID uint32
186 onuID uint32
187 uniID uint32
188}
189
Gamze Abakafee36392019-10-03 11:17:24 +0000190type schedQueue struct {
191 direction tp_pb.Direction
192 intfID uint32
193 onuID uint32
194 uniID uint32
195 tpID uint32
196 uniPort uint32
197 tpInst *tp.TechProfile
198 meterID uint32
199 flowMetadata *voltha.FlowMetadata
200}
201
Esin Karamanccb714b2019-11-29 15:02:06 +0000202type queueInfoBrief struct {
203 gemPortID uint32
204 servicePriority uint32
205}
206
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700207//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530208type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000209 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000210 deviceHandler *DeviceHandler
211 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000212 onuIdsLock sync.RWMutex
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530213 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
214 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
215 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
216 lockCache sync.RWMutex
Girish Gowdra3d633032019-12-10 16:37:05 +0530217 pendingFlowDelete sync.Map
218 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Esin Karamanccb714b2019-11-29 15:02:06 +0000219 perUserFlowHandleLock *mapmutex.Mutex
220 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 +0530221}
222
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700223//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530224func NewFlowManager(dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
manikkaraj kbf256be2019-03-25 00:13:48 +0530225 log.Info("Initializing flow manager")
226 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530227 var err error
228 var idx uint32
229
manikkaraj kbf256be2019-03-25 00:13:48 +0530230 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530231 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000232 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530233 if err = flowMgr.populateTechProfilePerPonPort(); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530234 log.Error("Error while populating tech profile mgr\n")
235 return nil
236 }
William Kurkian740a09c2019-10-23 17:07:38 -0400237 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530238 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
239 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
240 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo)
241 ponPorts := rMgr.DevInfo.GetPonPorts()
242 //Load the onugem info cache from kv store on flowmanager start
243 for idx = 0; idx < ponPorts; idx++ {
244 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(idx); err != nil {
245 log.Error("Failed to load onu gem info cache")
246 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530247 //Load flowID list per gem map per interface from the kvstore.
248 flowMgr.loadFlowIDlistForGem(idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530249 }
250 flowMgr.lockCache = sync.RWMutex{}
Girish Gowdra3d633032019-12-10 16:37:05 +0530251 flowMgr.pendingFlowDelete = sync.Map{}
252 flowMgr.perUserFlowHandleLock = mapmutex.NewMapMutex()
Esin Karamanccb714b2019-11-29 15:02:06 +0000253 flowMgr.interfaceToMcastQueueMap = make(map[uint32]*queueInfoBrief)
254 //load interface to multicast queue map from kv store
255 flowMgr.loadInterfaceToMulticastQueueMap()
manikkaraj kbf256be2019-03-25 00:13:48 +0530256 log.Info("Initialization of flow manager success!!")
257 return &flowMgr
258}
259
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700260func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700261 if direction == Upstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400262 log.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700263 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700264 } else if direction == Downstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400265 log.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700266 return uint64(flowID), nil
Esin Karamanccb714b2019-11-29 15:02:06 +0000267 } else if direction == Multicast {
268 log.Debug("multicast flow, shifting id")
269 return 0x2<<15 | uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400270 } else {
271 log.Debug("Unrecognized direction")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700272 return 0, fmt.Errorf("unrecognized direction %s", direction)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400273 }
274}
275
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700276func (f *OpenOltFlowMgr) registerFlow(flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400277 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700278 log.Fields{"device": f.deviceHandler.deviceID})
Gamze Abakafee36392019-10-03 11:17:24 +0000279 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
280 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
281 if !ok {
282 flowIDList = []uint32{deviceFlow.FlowId}
283 }
284 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
285 f.flowsUsedByGemPort[gemPK] = flowIDList
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530286 // update the flowids for a gem to the KVstore
287 f.resourceMgr.UpdateFlowIDsForGem(uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400288}
289
salmansiddiqui7ac62132019-08-22 03:58:50 +0000290func (f *OpenOltFlowMgr) divideAndAddFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32,
291 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
292 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000293 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530294 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400295 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530296
Manikkaraj kb1d51442019-07-23 10:41:02 -0400297 log.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000298 "classifier": classifierInfo, "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400299 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
300 // is because the flow is an NNI flow and there would be no onu resources associated with it
301 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400302 if onuID <= 0 {
Matt Jeanneret77199612019-07-26 18:08:35 -0400303 log.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530304 return
305 }
306
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530307 uni := getUniPortPath(intfID, int32(onuID), int32(uniID))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400308 log.Debugw("Uni port name", log.Fields{"uni": uni})
Girish Gowdra3d633032019-12-10 16:37:05 +0530309
310 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
311 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
312 allocID, gemPorts, TpInst = f.createTcontGemports(intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
313 if allocID == 0 || gemPorts == nil || TpInst == nil {
314 log.Error("alloc-id-gem-ports-tp-unavailable")
315 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
316 return
317 }
318 args := make(map[string]uint32)
319 args[IntfID] = intfID
320 args[OnuID] = onuID
321 args[UniID] = uniID
322 args[PortNo] = portNo
323 args[AllocID] = allocID
324
325 /* Flows can be added specific to gemport if p-bits are received.
326 * If no pbit mentioned then adding flows for all gemports
327 */
328 f.checkAndAddFlow(args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
329 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
330 } else {
331 log.Errorw("failed to acquire per user flow handle lock",
332 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400333 return
334 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530335}
336
salmansiddiqui7ac62132019-08-22 03:58:50 +0000337// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Gamze Abakafee36392019-10-03 11:17:24 +0000338func (f *OpenOltFlowMgr) CreateSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400339
Gamze Abakafee36392019-10-03 11:17:24 +0000340 log.Debugw("CreateSchedulerQueues", log.Fields{"Dir": sq.direction, "IntfID": sq.intfID,
341 "OnuID": sq.onuID, "UniID": sq.uniID, "TpID": sq.tpID, "MeterID": sq.meterID,
342 "TpInst": sq.tpInst, "flowMetadata": sq.flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400343
Gamze Abakafee36392019-10-03 11:17:24 +0000344 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000345 if err != nil {
346 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400347 }
348
349 /* Lets make a simple assumption that if the meter-id is present on the KV store,
350 * then the scheduler and queues configuration is applied on the OLT device
351 * in the given direction.
352 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000353
Manikkaraj kb1d51442019-07-23 10:41:02 -0400354 var SchedCfg *tp_pb.SchedulerConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000355 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400356 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000357 log.Error("Failed to get meter for intf %d, onuid %d, uniid %d", sq.intfID, sq.onuID, sq.uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400358 return err
359 }
360 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000361 if KvStoreMeter.MeterId == sq.meterID {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400362 log.Debug("Scheduler already created for upstream")
363 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400364 }
Gamze Abakafee36392019-10-03 11:17:24 +0000365 log.Errorw("Dynamic meter update not supported", log.Fields{"KvStoreMeterId": KvStoreMeter.MeterId, "MeterID-in-flow": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000366 return errors.New("invalid-meter-id-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400367 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000368
Gamze Abakafee36392019-10-03 11:17:24 +0000369 log.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": sq.meterID, "Direction": Direction})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000370
Gamze Abakafee36392019-10-03 11:17:24 +0000371 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000372 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Gamze Abakafee36392019-10-03 11:17:24 +0000373 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000374 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400375 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000376
377 if err != nil {
378 log.Errorw("Unable to get Scheduler config", log.Fields{"IntfID": sq.intfID, "Direction": sq.direction, "Error": err})
379 return err
380 }
381
Manikkaraj kb1d51442019-07-23 10:41:02 -0400382 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000383 if sq.flowMetadata != nil {
384 for _, meter := range sq.flowMetadata.Meters {
385 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400386 meterConfig = meter
387 log.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
388 break
389 }
390 }
391 } else {
392 log.Error("Flow-metadata-is-not-present-in-flow")
393 }
394 if meterConfig == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000395 log.Errorw("Could-not-get-meterbands-from-flowMetadata", log.Fields{"flowMetadata": sq.flowMetadata,
396 "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000397 return errors.New("failed-to-get-meter-from-flowMetadata")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400398 } else if len(meterConfig.Bands) < MaxMeterBand {
Gamze Abakafee36392019-10-03 11:17:24 +0000399 log.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000400 return errors.New("invalid-number-of-bands-in-meter")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401 }
402 cir := meterConfig.Bands[0].Rate
403 cbs := meterConfig.Bands[0].BurstSize
404 eir := meterConfig.Bands[1].Rate
405 ebs := meterConfig.Bands[1].BurstSize
406 pir := cir + eir
407 pbs := cbs + ebs
408 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
409
Gamze Abakafee36392019-10-03 11:17:24 +0000410 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400411
Girish Kumar8f73fe02019-12-09 13:19:37 +0000412 if err := f.pushSchedulerQueuesToDevice(sq, TrafficShaping, TrafficSched); err != nil {
413 log.Errorw("Failed to push traffic scheduler and queues to device", log.Fields{"intfID": sq.intfID, "direction": sq.direction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400414 return err
415 }
416
salmansiddiqui7ac62132019-08-22 03:58:50 +0000417 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400418 * store the meter id on the KV store, for further reference.
419 */
Gamze Abakafee36392019-10-03 11:17:24 +0000420 if err := f.resourceMgr.UpdateMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
421 log.Error("Failed to update meter id for onu %d, meterid %d", sq.onuID, sq.meterID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400422 return err
423 }
424 log.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
425 "Meter": meterConfig})
426 return nil
427}
428
Girish Kumar8f73fe02019-12-09 13:19:37 +0000429func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
430
431 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
432
433 if err != nil {
434 log.Errorw("Unable to construct traffic queue configuration", log.Fields{"intfID": sq.intfID, "direction": sq.direction})
435 return err
436 }
437
438 log.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": sq.direction, "TrafficScheds": TrafficSched})
439 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
440 IntfId: sq.intfID, OnuId: sq.onuID,
441 UniId: sq.uniID, PortNo: sq.uniPort,
442 TrafficScheds: TrafficSched}); err != nil {
443 log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
444 return err
445 }
446
447 // On receiving the CreateTrafficQueues request, the driver should create corresponding
448 // downstream queues.
449 log.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": sq.direction, "TrafficQueues": trafficQueues})
450 if _, err := f.deviceHandler.Client.CreateTrafficQueues(context.Background(),
451 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
452 UniId: sq.uniID, PortNo: sq.uniPort,
453 TrafficQueues: trafficQueues}); err != nil {
454 log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
455 return err
456 }
457
Esin Karamanccb714b2019-11-29 15:02:06 +0000458 if sq.direction == tp_pb.Direction_DOWNSTREAM {
459 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(sq.tpInst)
460 if len(multicastTrafficQueues) > 0 {
461 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
462 //assumed that there is only one queue per PON for the multicast service
463 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
464 //just put it in interfaceToMcastQueueMap to use for building group members
465 multicastQueuePerPonPort := multicastTrafficQueues[0]
466 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
467 gemPortID: multicastQueuePerPonPort.GemportId,
468 servicePriority: multicastQueuePerPonPort.Priority,
469 }
470 //also store the queue info in kv store
471 f.resourceMgr.AddMcastQueueForIntf(sq.intfID,
472 multicastQueuePerPonPort.GemportId,
473 multicastQueuePerPonPort.Priority)
474 }
475 }
476 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000477 return nil
478}
479
salmansiddiqui7ac62132019-08-22 03:58:50 +0000480// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
Gamze Abakafee36392019-10-03 11:17:24 +0000481func (f *OpenOltFlowMgr) RemoveSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400482
483 var Direction string
484 var SchedCfg *tp_pb.SchedulerConfig
485 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000486 log.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": sq.direction, "IntfID": sq.intfID,
487 "OnuID": sq.onuID, "UniID": sq.uniID, "UniPort": sq.uniPort})
488 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000489 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400490 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000491 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000492 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400493 Direction = "downstream"
494 }
495
Girish Kumar8f73fe02019-12-09 13:19:37 +0000496 if err != nil {
497 log.Errorw("Unable to get Scheduler config", log.Fields{"IntID": sq.intfID, "Direction": sq.direction, "Error": err})
498 return err
499 }
500
Gamze Abakafee36392019-10-03 11:17:24 +0000501 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400502 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000503 log.Errorf("Failed to get Meter for Onu %d", sq.onuID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400504 return err
505 }
506 if KVStoreMeter == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000507 log.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 -0400508 return nil
509 }
510 cir := KVStoreMeter.Bands[0].Rate
511 cbs := KVStoreMeter.Bands[0].BurstSize
512 eir := KVStoreMeter.Bands[1].Rate
513 ebs := KVStoreMeter.Bands[1].BurstSize
514 pir := cir + eir
515 pbs := cbs + ebs
516
517 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
518
Gamze Abakafee36392019-10-03 11:17:24 +0000519 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Girish Kumar8f73fe02019-12-09 13:19:37 +0000520
521 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
522 if err != nil {
523 log.Errorw("Unable to construct traffic queue configuration", log.Fields{"intfID": sq.intfID, "direction": sq.direction})
524 return err
525 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400526
527 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(context.Background(),
Gamze Abakafee36392019-10-03 11:17:24 +0000528 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
529 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400530 TrafficQueues: TrafficQueues}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000531 log.Errorw("Failed to remove traffic queues", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400532 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400533 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000534 log.Debug("Removed traffic queues successfully")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400535 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000536 IntfId: sq.intfID, OnuId: sq.onuID,
537 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400538 TrafficScheds: TrafficSched}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000539 log.Errorw("failed to remove traffic schedulers", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400540 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400541 }
542
salmansiddiqui7ac62132019-08-22 03:58:50 +0000543 log.Debug("Removed traffic schedulers successfully")
544
545 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400546 * delete the meter id on the KV store.
547 */
Gamze Abakafee36392019-10-03 11:17:24 +0000548 err = f.resourceMgr.RemoveMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400549 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000550 log.Errorf("Failed to remove meter for onu %d, meter id %d", sq.onuID, KVStoreMeter.MeterId)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000551 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400552 }
553 log.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
554 return err
555}
556
Gamze Abakafee36392019-10-03 11:17:24 +0000557// This function allocates tconts and GEM ports for an ONU
558func (f *OpenOltFlowMgr) createTcontGemports(intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) (uint32, []uint32, *tp.TechProfile) {
559 var allocIDs []uint32
560 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530561 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530562 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000563 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000564
565 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(intfID, onuID, uniID)
566 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400567
568 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530569
570 log.Infow("creating-new-tcont-and-gem", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
571
Manikkaraj kb1d51442019-07-23 10:41:02 -0400572 // Check tech profile instance already exists for derived port name
Girish Gowdra54934262019-11-13 14:19:55 +0530573 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000574 if techProfileInstance == nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530575 log.Infow("tp-instance-not-found--creating-new", log.Fields{"path": tpPath})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000576 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(TpID, uni, intfID)
577 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530578 // This should not happen, something wrong in KV backend transaction
Girish Kumar8f73fe02019-12-09 13:19:37 +0000579 log.Errorw("tp-instance-create-failed", log.Fields{"error": err, "tpID": TpID})
Gamze Abakafee36392019-10-03 11:17:24 +0000580 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530581 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000582 f.resourceMgr.UpdateTechProfileIDForOnu(intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530583 } else {
584 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
Girish Gowdra3d633032019-12-10 16:37:05 +0530585 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530586 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400587 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000588 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
589 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
590 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400591 log.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000592 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400593 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530594 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400595 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000596 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
597 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
598 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400599 log.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000600 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400601 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530602 }
Gamze Abakafee36392019-10-03 11:17:24 +0000603
604 allocID := techProfileInstance.UsScheduler.AllocID
Gamze Abakafee36392019-10-03 11:17:24 +0000605 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Gamze Abakafee36392019-10-03 11:17:24 +0000606 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400607 }
Gamze Abakafee36392019-10-03 11:17:24 +0000608
Girish Gowdra3d633032019-12-10 16:37:05 +0530609 if tpInstanceExists {
610 return allocID, gemPortIDs, techProfileInstance
611 }
612
613 allocIDs = appendUnique(allocIDs, allocID)
614 for _, gemPortID := range gemPortIDs {
615 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
616 }
617
Gamze Abakafee36392019-10-03 11:17:24 +0000618 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocIDs": allocIDs, "gemports": allgemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530619 // Send Tconts and GEM ports to KV store
Gamze Abakafee36392019-10-03 11:17:24 +0000620 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000621 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530622}
623
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700624func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530625
626 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700627 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530628 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700629 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530630 log.Error("Errow while uploading allocID to KV store")
631 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700632 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530633 log.Error("Errow while uploading GEMports to KV store")
634 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700635 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530636 log.Error("Errow while uploading gemtopon map to KV store")
637 }
638 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400639 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700640 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400641 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530642}
643
644func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000645 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530646 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000647 for _, intfID := range techRange.IntfIds {
648 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400649 tpCount++
salmansiddiqui7ac62132019-08-22 03:58:50 +0000650 log.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530651 }
652 }
653 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400654 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530655 log.Errorw("Error while populating techprofile",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400656 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000657 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530658 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400659 log.Infow("Populated techprofile for ponports successfully",
660 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530661 return nil
662}
663
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700664func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530665 portNo uint32, uplinkClassifier map[string]interface{},
666 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700667 allocID uint32, gemportID uint32) {
668 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530669 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700670 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700671 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530672 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530673}
674
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700675func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530676 portNo uint32, downlinkClassifier map[string]interface{},
677 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700678 allocID uint32, gemportID uint32) {
679 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530680 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
681 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400682 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
683 if vlan, exists := downlinkClassifier[VlanVid]; exists {
684 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700685 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400686 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
687 log.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
688 return
689 }
690 }
691 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530692 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400693
Manikkaraj k884c1242019-04-11 16:26:42 +0530694 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700695 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400696 // vlan_vid is a uint32. must be type asserted as such or conversion fails
697 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530698 if ok {
699 downlinkAction[VlanVid] = dlClVid & 0xfff
700 } else {
701 log.Error("dl-classifier-vid-type-conversion-failed")
702 return
703 }
704
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700705 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700706 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530707}
708
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700709func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530710 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700711 allocID uint32, gemPortID uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530712 var networkIntfID uint32
Manikkaraj k884c1242019-04-11 16:26:42 +0530713 /* One of the OLT platform (Broadcom BAL) requires that symmetric
714 flows require the same flow_id to be used across UL and DL.
715 Since HSIA flow is the only symmetric flow currently, we need to
716 re-use the flow_id across both direction. The 'flow_category'
717 takes priority over flow_cookie to find any available HSIA_FLOW
718 id for the ONU.
719 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700720 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
721 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530722 "logicalFlow": *logicalFlow})
Gamze Abakafee36392019-10-03 11:17:24 +0000723 var vlanPbit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400724 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000725 vlanPbit = classifier[VlanPcp].(uint32)
726 log.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400727 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700728 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Girish Gowdra3d633032019-12-10 16:37:05 +0530729 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
730 log.Debug("Flow-exists--not-re-adding")
731 return
732 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530733 flowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530734 if err != nil {
735 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
736 return
737 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700738 var classifierProto *openoltpb2.Classifier
739 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530740 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
741 log.Error("Error in making classifier protobuf for hsia flow")
742 return
743 }
744 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
745 if actionProto = makeOpenOltActionField(action); actionProto == nil {
746 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
747 return
748 }
749 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530750 networkIntfID, err = getNniIntfID(classifier, action)
751 if err != nil {
752 log.Error("Failed to get nniIntf ID")
753 return
754 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700755 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
756 OnuId: int32(onuID),
757 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000758 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530759 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700760 AllocId: int32(allocID),
761 NetworkIntfId: int32(networkIntfID),
762 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530763 Classifier: classifierProto,
764 Action: actionProto,
765 Priority: int32(logicalFlow.Priority),
766 Cookie: logicalFlow.Cookie,
767 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400768 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530769 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530770 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
Manikkaraj k884c1242019-04-11 16:26:42 +0530771 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
772 flow.OnuId,
773 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400774 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530775 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
776 return
777 }
778 }
779}
Esin Karamanae41e2b2019-12-17 18:13:13 +0000780
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700781func (f *OpenOltFlowMgr) addDHCPTrapFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32) {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530782
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700783 var dhcpFlow openoltpb2.Flow
784 var actionProto *openoltpb2.Action
785 var classifierProto *openoltpb2.Classifier
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530786 var flowID uint32
787 networkIntfID, err := getNniIntfID(classifier, action)
788 if err != nil {
789 log.Error("Failed to get nniIntf ID")
790 return
791 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530792
793 // Clear the action map
794 for k := range action {
795 delete(action, k)
796 }
797
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700798 action[TrapToHost] = true
799 classifier[UDPSrc] = uint32(68)
800 classifier[UDPDst] = uint32(67)
801 classifier[PacketTagType] = SingleTag
802 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530803
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700804 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Girish Gowdra3d633032019-12-10 16:37:05 +0530805 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
806 log.Debug("Flow-exists--not-re-adding")
807 return
808 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530809
Girish Gowdra3d633032019-12-10 16:37:05 +0530810 flowID, err = f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, DhcpFlow, 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530811
812 if err != nil {
Girish Gowdra3d633032019-12-10 16:37:05 +0530813 log.Errorw("flowId unavailable for UL DHCP", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530814 return
815 }
816
817 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
818
819 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
820 log.Error("Error in making classifier protobuf for ul flow")
821 return
822 }
823 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
824 if actionProto = makeOpenOltActionField(action); actionProto == nil {
825 log.Error("Error in making action protobuf for ul flow")
826 return
827 }
828
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700829 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
830 OnuId: int32(onuID),
831 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530832 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700833 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700834 AllocId: int32(allocID),
835 NetworkIntfId: int32(networkIntfID),
836 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530837 Classifier: classifierProto,
838 Action: actionProto,
839 Priority: int32(logicalFlow.Priority),
840 Cookie: logicalFlow.Cookie,
841 PortNo: portNo}
842
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400843 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530844 log.Debug("DHCP UL flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530845 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530846 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
847 dhcpFlow.OnuId,
848 dhcpFlow.UniId,
849 dhcpFlow.FlowId, flowsToKVStore); err != nil {
850 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
851 return
852 }
853 }
854
manikkaraj kbf256be2019-03-25 00:13:48 +0530855 return
856}
857
Esin Karamanae41e2b2019-12-17 18:13:13 +0000858//addIGMPTrapFlow creates IGMP trap-to-host flow
859func (f *OpenOltFlowMgr) addIGMPTrapFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
860 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32) {
861 f.addUpstreamTrapFlow(intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow)
862}
863
864//addUpstreamTrapFlow creates a trap-to-host flow
865func (f *OpenOltFlowMgr) addUpstreamTrapFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
866 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string) {
867
868 var flow openoltpb2.Flow
869 var actionProto *openoltpb2.Action
870 var classifierProto *openoltpb2.Classifier
871
872 networkIntfID, err := getNniIntfID(classifier, action)
873 if err != nil {
874 log.Error("Failed to get nniIntf ID")
875 return
876 }
877
878 // Clear the action map
879 for k := range action {
880 delete(action, k)
881 }
882
883 action[TrapToHost] = true
884 classifier[PacketTagType] = SingleTag
885 delete(classifier, VlanVid)
886
887 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
888 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
889 log.Debug("Flow-exists--not-re-adding")
890 return
891 }
892
893 flowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, flowType, 0, 0 /*classifier[VLAN_PCP].(uint32)*/)
894
895 if err != nil {
896 log.Errorw("flowId unavailable for upstream trap flow", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie, "flowType": flowType})
897 return
898 }
899
900 log.Debugw("Creating upstream trap flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID, "flowType": flowType})
901
902 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
903 log.Error("Error in making classifier protobuf for ul flow")
904 return
905 }
906 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
907 if actionProto = makeOpenOltActionField(action); actionProto == nil {
908 log.Error("Error in making action protobuf for ul flow")
909 return
910 }
911
912 flow = openoltpb2.Flow{AccessIntfId: int32(intfID),
913 OnuId: int32(onuID),
914 UniId: int32(uniID),
915 FlowId: flowID,
916 FlowType: Upstream,
917 AllocId: int32(allocID),
918 NetworkIntfId: int32(networkIntfID),
919 GemportId: int32(gemPortID),
920 Classifier: classifierProto,
921 Action: actionProto,
922 Priority: int32(logicalFlow.Priority),
923 Cookie: logicalFlow.Cookie,
924 PortNo: portNo}
925
926 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
927 log.Debugf("%s UL flow added to device successfully", flowType)
928
929 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
930 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
931 flow.OnuId,
932 flow.UniId,
933 flow.FlowId, flowsToKVStore); err != nil {
934 log.Errorw("Error uploading UL flow into KV store", log.Fields{"flow": flow, "error": err})
935 return
936 }
937 }
938
939 return
940}
941
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700942// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530943func (f *OpenOltFlowMgr) addEAPOLFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32, classifier map[string]interface{}, action map[string]interface{}) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700944 log.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 +0530945
946 uplinkClassifier := make(map[string]interface{})
947 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +0530948
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700949 var upstreamFlow openoltpb2.Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530950 var networkIntfID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530951
952 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700953 uplinkClassifier[EthType] = uint32(EapEthType)
954 uplinkClassifier[PacketTagType] = SingleTag
955 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530956 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700957 uplinkAction[TrapToHost] = true
958 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
Girish Gowdra3d633032019-12-10 16:37:05 +0530959 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
960 log.Debug("Flow-exists--not-re-adding")
961 return
962 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530963 //Add Uplink EAPOL Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530964 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530965 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700966 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530967 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530968 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700969 var classifierProto *openoltpb2.Classifier
970 var actionProto *openoltpb2.Action
971 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530972
973 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
974 log.Error("Error in making classifier protobuf for ul flow")
975 return
976 }
977 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
978 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
979 log.Error("Error in making action protobuf for ul flow")
980 return
981 }
982 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530983 networkIntfID, err = getNniIntfID(classifier, action)
984 if err != nil {
985 log.Error("Failed to get nniIntf ID")
986 return
987 }
988
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700989 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
990 OnuId: int32(onuID),
991 UniId: int32(uniID),
992 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700993 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700994 AllocId: int32(allocID),
995 NetworkIntfId: int32(networkIntfID),
996 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530997 Classifier: classifierProto,
998 Action: actionProto,
999 Priority: int32(logicalFlow.Priority),
1000 Cookie: logicalFlow.Cookie,
1001 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001002 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301003 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001004 flowCategory := "EAPOL"
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301005 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
manikkaraj kbf256be2019-03-25 00:13:48 +05301006 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
1007 upstreamFlow.OnuId,
1008 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001009 upstreamFlow.FlowId,
1010 /* lowCategory, */
1011 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +05301012 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
1013 return
1014 }
1015 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301016
manikkaraj kbf256be2019-03-25 00:13:48 +05301017 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
1018}
1019
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001020func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
1021 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001022
1023 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1024 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1025 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
1026 vid := vlanID & VlanvIDMask
1027 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001028 classifier.OVid = vid
1029 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301030 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001031 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1032 vid := uint32(metadata)
1033 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001034 classifier.IVid = vid
1035 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301036 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001037 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001038 if vlanPcp == 0 {
1039 classifier.OPbits = VlanPCPMask
1040 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001041 classifier.OPbits = vlanPcp & VlanPCPMask
Manikkaraj kb1d51442019-07-23 10:41:02 -04001042 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301043 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001044 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1045 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1046 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1047 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001048 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001049 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1050 classifier.PktTagType = pktTagType
1051
1052 switch pktTagType {
1053 case SingleTag:
1054 case DoubleTag:
1055 case Untagged:
1056 default:
manikkaraj kbf256be2019-03-25 00:13:48 +05301057 log.Error("Invalid tag type in classifier") // should not hit
1058 return nil
1059 }
1060 }
1061 return &classifier
1062}
1063
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001064func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
1065 var actionCmd openoltpb2.ActionCmd
1066 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301067 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001068 if _, ok := actionInfo[PopVlan]; ok {
1069 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301070 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001071 } else if _, ok := actionInfo[PushVlan]; ok {
1072 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301073 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001074 } else if _, ok := actionInfo[TrapToHost]; ok {
1075 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301076 } else {
1077 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
1078 return nil
1079 }
1080 return &action
1081}
1082
Manikkaraj kb1d51442019-07-23 10:41:02 -04001083func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
1084 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +05301085}
1086
Gamze Abakafee36392019-10-03 11:17:24 +00001087// DeleteTechProfileInstances removes the tech profile instances from persistent storage
1088func (f *OpenOltFlowMgr) DeleteTechProfileInstances(intfID uint32, onuID uint32, uniID uint32, sn string) error {
1089 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001090 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001091 for _, tpID := range tpIDList {
1092 if err := f.DeleteTechProfileInstance(intfID, onuID, uniID, uniPortName, tpID); err != nil {
1093 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
Girish Gowdra54934262019-11-13 14:19:55 +05301094 // return err
1095 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001096 }
1097 }
1098 return nil
1099}
1100
1101// DeleteTechProfileInstance removes the tech profile instance from persistent storage
1102func (f *OpenOltFlowMgr) DeleteTechProfileInstance(intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
1103 if uniPortName == "" {
1104 uniPortName = fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1105 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001106 if err := f.techprofile[intfID].DeleteTechProfileInstance(tpID, uniPortName); err != nil {
1107 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
1108 return err
1109 }
1110 return nil
1111}
1112
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001113func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301114 if len(classifier) == 0 { // should never happen
1115 log.Error("Invalid classfier object")
1116 return 0
1117 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301118 log.Debugw("generating flow store cookie", log.Fields{"classifier": classifier, "gemPortID": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301119 var jsonData []byte
1120 var flowString string
1121 var err error
1122 // TODO: Do we need to marshall ??
1123 if jsonData, err = json.Marshal(classifier); err != nil {
1124 log.Error("Failed to encode classifier")
1125 return 0
1126 }
1127 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001128 if gemPortID != 0 {
1129 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301130 }
1131 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001132 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301133 hash := big.NewInt(0)
1134 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301135 generatedHash := hash.Uint64()
1136 log.Debugw("hash generated", log.Fields{"hash": generatedHash})
1137 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301138}
1139
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301140func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32, logicalFlowID uint64) *[]rsrcMgr.FlowInfo {
1141 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001142 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001143 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1144 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1145 */
1146 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001147 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001148 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001149 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001150 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001151 // Get existing flows matching flowid for given subscriber from KV store
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301152 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001153 if existingFlows != nil {
1154 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001155 //for _, f := range *existingFlows {
1156 // flows = append(flows, f)
1157 //}
1158 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001159 }
1160 log.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 +05301161 return &flows
1162}
1163
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001164//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1165// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1166// var intfId uint32
1167// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1168// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1169// */
1170// if flow.AccessIntfId != -1 {
1171// intfId = uint32(flow.AccessIntfId)
1172// } else {
1173// intfId = uint32(flow.NetworkIntfId)
1174// }
1175// // Get existing flows matching flowid for given subscriber from KV store
1176// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1177// if existingFlows != nil {
1178// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
1179// for _, f := range *existingFlows {
1180// flows = append(flows, f)
1181// }
1182// }
1183// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
1184// return &flows
1185//}
1186
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001187func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -04001188 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001189 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -04001190 log.Debug("Error while Storing flow into KV store")
1191 return err
1192 }
1193 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301194 return nil
1195}
1196
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001197func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001198
1199 var intfID uint32
1200 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1201 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1202 */
1203 if deviceFlow.AccessIntfId != -1 {
1204 intfID = uint32(deviceFlow.AccessIntfId)
1205 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001206 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001207 intfID = uint32(deviceFlow.NetworkIntfId)
1208 }
1209
manikkaraj kbf256be2019-03-25 00:13:48 +05301210 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1211 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001212
1213 st, _ := status.FromError(err)
1214 if st.Code() == codes.AlreadyExists {
Gamze Abakafee36392019-10-03 11:17:24 +00001215 log.Debug("Flow already exists", log.Fields{"err": err, "deviceFlow": deviceFlow})
Girish Gowdra3d633032019-12-10 16:37:05 +05301216 return true
manikkaraj kbf256be2019-03-25 00:13:48 +05301217 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001218
1219 if err != nil {
1220 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001221 f.resourceMgr.FreeFlowID(intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001222 return false
1223 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301224 if deviceFlow.GemportId != -1 {
1225 // No need to register the flow if it is a trap on nni flow.
1226 f.registerFlow(logicalFlow, deviceFlow)
1227 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301228 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001229 return true
1230}
1231
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001232func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001233 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1234 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1235 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001236 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
1237 log.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
1238 //Assume the flow is removed
1239 return true
1240 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001241 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1242 return false
serkant.uluderya245caba2019-09-24 23:15:29 -07001243
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001244 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001245 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301246 return true
1247}
1248
1249/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1250 //update core flows_proxy : flows_proxy.update('/', flows)
1251}
1252
1253func generateStoredId(flowId uint32, direction string)uint32{
1254
David K. Bainbridge82efc492019-09-04 09:57:11 -07001255 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301256 log.Debug("Upstream flow shifting flowid")
1257 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001258 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301259 log.Debug("Downstream flow not shifting flowid")
1260 return flowId
1261 }else{
1262 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1263 return flowId
1264 }
1265}
1266
1267*/
1268
Humera Kouser94d7a842019-08-25 19:04:32 -04001269func (f *OpenOltFlowMgr) addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
1270
1271 classifierInfo := make(map[string]interface{})
1272 actionInfo := make(map[string]interface{})
1273
1274 classifierInfo[EthType] = uint32(LldpEthType)
1275 classifierInfo[PacketTagType] = Untagged
1276 actionInfo[TrapToHost] = true
1277
1278 // LLDP flow is installed to trap LLDP packets on the NNI port.
1279 // We manage flow_id resource pool on per PON port basis.
1280 // Since this situation is tricky, as a hack, we pass the NNI port
1281 // index (network_intf_id) as PON port Index for the flow_id resource
1282 // pool. Also, there is no ONU Id available for trapping LLDP packets
1283 // on NNI port, use onu_id as -1 (invalid)
1284 // ****************** CAVEAT *******************
1285 // This logic works if the NNI Port Id falls within the same valid
1286 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1287 // we need to have a re-look at this.
1288 // *********************************************
1289
1290 var onuID = -1
1291 var uniID = -1
1292 var gemPortID = -1
1293
1294 var networkInterfaceID = IntfIDFromNniPortNum(portNo)
1295 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301296 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Humera Kouser94d7a842019-08-25 19:04:32 -04001297 log.Debug("Flow-exists--not-re-adding")
1298 return
1299 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301300 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001301
1302 if err != nil {
1303 log.Errorw("Flow id unavailable for LLDP traponNNI flow", log.Fields{"error": err})
1304 return
1305 }
1306 var classifierProto *openoltpb2.Classifier
1307 var actionProto *openoltpb2.Action
1308 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1309 log.Error("Error in making classifier protobuf for LLDP trap on nni flow")
1310 return
1311 }
1312 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1313 if actionProto = makeOpenOltActionField(actionInfo); actionProto == nil {
1314 log.Error("Error in making action protobuf for LLDP trap on nni flow")
1315 return
1316 }
1317 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1318
1319 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1320 OnuId: int32(onuID), // OnuId not required
1321 UniId: int32(uniID), // UniId not used
1322 FlowId: flowID,
1323 FlowType: Downstream,
1324 NetworkIntfId: int32(networkInterfaceID),
1325 GemportId: int32(gemPortID),
1326 Classifier: classifierProto,
1327 Action: actionProto,
1328 Priority: int32(flow.Priority),
1329 Cookie: flow.Cookie,
1330 PortNo: portNo}
1331 if ok := f.addFlowToDevice(flow, &downstreamflow); ok {
1332 log.Debug("LLDP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301333 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, flow.Id)
Humera Kouser94d7a842019-08-25 19:04:32 -04001334 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1335 int32(onuID),
1336 int32(uniID),
1337 flowID, flowsToKVStore); err != nil {
1338 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1339 }
1340 }
1341 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301342}
1343
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301344func getUniPortPath(intfID uint32, onuID int32, uniID int32) string {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001345 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1346}
1347
1348//getOnuChildDevice to fetch onu
1349func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1350 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1351 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1352 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301353 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001354 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301355 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301356 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301357 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1358 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301359}
1360
1361func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001362 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301363 return nil
1364}
1365
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001366func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1367 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301368}
1369
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001370func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001371 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001372 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001373 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001374 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001375}
1376
Girish Gowdra6b130582019-11-20 16:45:20 +05301377func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1378 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1379 if err != nil {
1380 log.Errorw("error fetching child device from core", log.Fields{"onuId": onuID})
1381 return err
1382 }
1383
1384 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
1385 log.Debugw("sending gem port delete to openonu adapter", log.Fields{"msg": *delGemPortMsg})
1386 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1387 delGemPortMsg,
1388 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
1389 f.deviceHandler.deviceType,
1390 onuDevice.Type,
1391 onuDevice.Id,
1392 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
1393 log.Errorw("failure sending del gem port to onu adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1394 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1395 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1396 return sendErr
1397 }
1398 log.Debugw("success sending del gem port to onu adapter", log.Fields{"msg": delGemPortMsg})
1399 return nil
1400}
1401
1402func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1403 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1404 if err != nil {
1405 log.Errorw("error fetching child device from core", log.Fields{"onuId": onuID})
1406 return err
1407 }
1408
1409 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
1410 log.Debugw("sending tcont delete to openonu adapter", log.Fields{"msg": *delTcontMsg})
1411 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1412 delTcontMsg,
1413 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
1414 f.deviceHandler.deviceType,
1415 onuDevice.Type,
1416 onuDevice.Id,
1417 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
1418 log.Errorw("failure sending del tcont to onu adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1419 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1420 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1421 return sendErr
1422 }
1423 log.Debugw("success sending del tcont to onu adapter", log.Fields{"msg": delTcontMsg})
1424 return nil
1425}
1426
Girish Gowdra3d633032019-12-10 16:37:05 +05301427func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1428 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1429 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1430 if val.(int) > 0 {
1431 pnFlDels := val.(int) - 1
1432 if pnFlDels > 0 {
1433 log.Debugw("flow delete succeeded, more pending",
1434 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1435 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1436 } else {
1437 log.Debugw("all pending flow deletes handled, removing entry from map",
1438 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1439 f.pendingFlowDelete.Delete(pnFlDelKey)
1440 }
1441 }
1442 } else {
1443 log.Debugw("no pending delete flows found",
1444 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1445
1446 }
1447
1448}
1449
Girish Gowdrac3037402020-01-22 20:29:53 +05301450// Once the gemport is released for a given onu, it also has to be cleared from local cache
1451// which was used for deriving the gemport->logicalPortNo during packet-in.
1452// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1453// is conveyed to ONOS during packet-in OF message.
1454func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(intfID uint32, onuID uint32, gemPortID uint32) {
1455 f.lockCache.Lock()
1456 defer f.lockCache.Unlock()
1457 onugem := f.onuGemInfo[intfID]
1458 for _, onu := range onugem {
1459 if onu.OnuID == onuID {
1460 for i, gem := range onu.GemPorts {
1461 // If the gemport is found, delete it from local cache.
1462 if gem == gemPortID {
1463 onu.GemPorts = append(onu.GemPorts[:i], onu.GemPorts[i+1:]...)
1464 log.Debugw("removed gemport from local cache",
1465 log.Fields{"intfID": intfID, "onuID": onuID, "gemPortID": gemPortID})
1466 break
1467 }
1468 }
1469 break
1470 }
1471 }
1472}
1473
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301474//clearResources clears pon resources in kv store and the device
1475func (f *OpenOltFlowMgr) clearResources(flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
1476 gemPortID int32, flowID uint32, flowDirection string,
1477 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001478
Chaitrashree G S90a17952019-11-14 21:51:21 -05001479 tpID, err := getTpIDFromFlow(flow)
1480 if err != nil {
1481 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID})
1482 return err
1483 }
Gamze Abakafee36392019-10-03 11:17:24 +00001484
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001485 if len(updatedFlows) >= 0 {
1486 // There are still flows referencing the same flow_id.
1487 // So the flow should not be freed yet.
1488 // For ex: Case of HSIA where same flow is shared
1489 // between DS and US.
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301490 f.updateFlowInfoToKVStore(int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001491 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05301492 // Do this for subscriber flows only (not trap from NNI flows)
1493 if onuID != -1 && uniID != -1 {
1494 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1495 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
1496 log.Debugw("creating entry for pending flow delete",
1497 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1498 f.pendingFlowDelete.Store(pnFlDelKey, 1)
1499 } else {
1500 pnFlDels := val.(int) + 1
1501 log.Debugw("updating flow delete entry",
1502 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1503 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1504 }
1505
1506 defer f.deletePendingFlows(Intf, onuID, uniID)
1507 }
1508
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301509 log.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
1510 f.resourceMgr.FreeFlowID(Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001511
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301512 uni := getUniPortPath(Intf, onuID, uniID)
1513 tpPath := f.getTPpath(Intf, uni, tpID)
Gamze Abakafee36392019-10-03 11:17:24 +00001514 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301515 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(tpID, tpPath)
Gamze Abakafee36392019-10-03 11:17:24 +00001516 if err != nil { // This should not happen, something wrong in KV backend transaction
1517 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301518 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001519 }
1520 if techprofileInst == nil {
1521 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301522 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001523 }
1524
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301525 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001526 if f.isGemPortUsedByAnotherFlow(gemPK) {
1527 flowIDs := f.flowsUsedByGemPort[gemPK]
1528 for i, flowIDinMap := range flowIDs {
1529 if flowIDinMap == flowID {
1530 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301531 // everytime flowsUsedByGemPort cache is updated the same should be updated
1532 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001533 f.flowsUsedByGemPort[gemPK] = flowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301534 f.resourceMgr.UpdateFlowIDsForGem(Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00001535 break
1536 }
1537 }
1538 log.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301539 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001540 }
Gamze Abakafee36392019-10-03 11:17:24 +00001541 log.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301542 f.resourceMgr.RemoveGemPortIDForOnu(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001543 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1544 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301545 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(uint32(gemPortID), Intf)
Girish Gowdrac3037402020-01-22 20:29:53 +05301546 f.deleteGemPortFromLocalCache(Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001547 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301548 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1549 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001550 delete(f.flowsUsedByGemPort, gemPK)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301551 f.resourceMgr.DeleteFlowIDsForGem(Intf, uint32(gemPortID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301552 f.resourceMgr.FreeGemPortID(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001553 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05301554 // Delete the gem port on the ONU.
1555 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1556 log.Errorw("error processing delete gem-port towards onu",
1557 log.Fields{"err": err, "pon": Intf, "onuID": onuID, "uniID": uniID, "gemPortId": gemPortID})
1558 }
Gamze Abakafee36392019-10-03 11:17:24 +00001559
Girish Gowdra54934262019-11-13 14:19:55 +05301560 ok, _ := f.isTechProfileUsedByAnotherGem(Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001561 if !ok {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301562 f.resourceMgr.RemoveTechProfileIDForOnu(Intf, uint32(onuID), uint32(uniID), tpID)
1563 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1564 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1565 f.DeleteTechProfileInstance(Intf, uint32(onuID), uint32(uniID), "", tpID)
1566 f.resourceMgr.FreeAllocID(Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301567 // Delete the TCONT on the ONU.
1568 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
1569 log.Errorw("error processing delete tcont towards onu",
1570 log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID, "allocId": techprofileInst.UsScheduler.AllocID})
1571 }
Gamze Abakafee36392019-10-03 11:17:24 +00001572 }
1573 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001574 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301575 return nil
1576}
1577
1578func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowDirection string) {
1579
1580 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
Esin Karamanccb714b2019-11-29 15:02:06 +00001581
1582 if flowDirection == Multicast {
1583 f.clearMulticastFlowFromResourceManager(flow)
1584 return
1585 }
1586
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301587 var updatedFlows []rsrcMgr.FlowInfo
1588 var flowID uint32
1589 var onuID, uniID int32
1590 classifierInfo := make(map[string]interface{})
1591
1592 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1593 if err != nil {
1594 log.Error(err)
1595 return
1596 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301597
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301598 onuID = int32(onu)
1599 uniID = int32(uni)
1600
1601 for _, field := range flows.GetOfbFields(flow) {
1602 if field.Type == flows.IP_PROTO {
1603 classifierInfo[IPProto] = field.GetIpProto()
1604 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1605 }
1606 }
1607 log.Debugw("Extracted access info from flow to be deleted",
1608 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1609
1610 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1611 onuID = -1
1612 uniID = -1
1613 log.Debug("Trap on nni flow set oni, uni to -1")
1614 Intf = IntfIDFromNniPortNum(inPort)
1615 }
1616 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(Intf, onuID, uniID)
1617 for _, flowID = range flowIds {
1618 flowInfo := f.resourceMgr.GetFlowIDInfo(Intf, onuID, uniID, flowID)
1619 if flowInfo == nil {
1620 log.Debugw("No FlowInfo found found in KV store",
1621 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1622 return
1623 }
1624 updatedFlows = nil
1625 for _, flow := range *flowInfo {
1626 updatedFlows = append(updatedFlows, flow)
1627 }
1628
1629 for i, storedFlow := range updatedFlows {
1630 if flow.Id == storedFlow.LogicalFlowID {
1631 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1632 log.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
1633 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1634 log.Debug("Flow removed from device successfully")
1635 //Remove the Flow from FlowInfo
1636 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1637 err = f.clearResources(flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1638 flowID, flowDirection, portNum, updatedFlows)
1639 if err != nil {
1640 log.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
1641 return
1642 }
1643 } else {
1644 log.Error("Failed to remove flow from device")
1645 return
1646 }
1647 }
1648 }
1649 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001650}
1651
Esin Karamanccb714b2019-11-29 15:02:06 +00001652//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
1653// clears resources reserved for this multicast flow
1654func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(flow *ofp.OfpFlowStats) {
1655 classifierInfo := make(map[string]interface{})
1656 formulateClassifierInfoFromFlow(classifierInfo, flow)
1657 inPort, err := f.getInPortOfMulticastFlow(classifierInfo)
1658
1659 if err != nil {
1660 log.Warnw("No inPort found. Cannot release resources of the multicast flow.", log.Fields{"flowId:": flow.Id})
1661 return
1662 }
1663
1664 networkInterfaceID := IntfIDFromNniPortNum(inPort)
1665 var onuID = int32(NoneOnuID)
1666 var uniID = int32(NoneUniID)
1667 var flowID uint32
1668 var updatedFlows []rsrcMgr.FlowInfo
1669
1670 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(networkInterfaceID, onuID, uniID)
1671
1672 for _, flowID = range flowIds {
1673 flowInfo := f.resourceMgr.GetFlowIDInfo(networkInterfaceID, onuID, uniID, flowID)
1674 if flowInfo == nil {
1675 log.Debugw("No multicast FlowInfo found in the KV store",
1676 log.Fields{"Intf": networkInterfaceID, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1677 continue
1678 }
1679 updatedFlows = nil
1680 for _, flow := range *flowInfo {
1681 updatedFlows = append(updatedFlows, flow)
1682 }
1683 for i, storedFlow := range updatedFlows {
1684 if flow.Id == storedFlow.LogicalFlowID {
1685 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1686 log.Debugw("Multicast flow to be deleted", log.Fields{"flow": storedFlow})
1687 //remove from device
1688 if ok := f.removeFlowFromDevice(&removeFlowMessage); !ok {
1689 log.Errorw("Failed to remove multicast flow from device", log.Fields{"flowId": flow.Id})
1690 return
1691 }
1692 log.Debugw("Multicast flow removed from device successfully", log.Fields{"flowId": flow.Id})
1693 //Remove the Flow from FlowInfo
1694 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1695 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
1696 log.Error("Failed to delete multicast flow from the KV store", log.Fields{"flow": storedFlow, "err": err})
1697 return
1698 }
1699 //release flow id
1700 log.Debugw("Releasing multicast flow id", log.Fields{"flowId": flowID, "interfaceID": networkInterfaceID})
1701 f.resourceMgr.FreeFlowID(uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
1702 }
1703 }
1704 }
1705}
1706
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001707//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001708func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1709 log.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301710 var direction string
1711 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001712
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301713 for _, action := range flows.GetActions(flow) {
1714 if action.Type == flows.OUTPUT {
1715 if out := action.GetOutput(); out != nil {
1716 actionInfo[Output] = out.GetPort()
1717 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
1718 } else {
1719 log.Error("Invalid output port in action")
1720 return
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001721 }
1722 }
1723 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001724
1725 if flows.HasGroup(flow) {
1726 direction = Multicast
1727 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301728 direction = Upstream
1729 } else {
1730 direction = Downstream
1731 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301732 f.clearFlowFromResourceManager(flow, direction) //TODO: Take care of the limitations
1733
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001734 return
1735}
1736
Girish Gowdra3d633032019-12-10 16:37:05 +05301737func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
1738 uniID uint32, ch chan bool) {
1739 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1740 for {
1741 select {
1742 case <-time.After(20 * time.Millisecond):
1743 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
1744 log.Debug("pending flow deletes completed")
1745 ch <- true
1746 return
1747 }
1748 case <-ctx.Done():
1749 log.Error("flow delete wait handler routine canceled")
1750 return
1751 }
1752 }
1753}
1754
Esin Karamanae41e2b2019-12-17 18:13:13 +00001755//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
1756func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
1757 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
1758 if ethType, ok := classifierInfo[EthType]; ok {
1759 if ethType.(uint32) == IPv4EthType {
1760 if ipProto, ok := classifierInfo[IPProto]; ok {
1761 if ipProto.(uint32) == IgmpProto {
1762 return true
1763 }
1764 }
1765 }
1766 }
1767 }
1768 return false
1769}
1770
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001771// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301772// nolint: gocyclo
Manikkaraj kb1d51442019-07-23 10:41:02 -04001773func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001774 classifierInfo := make(map[string]interface{})
1775 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001776 var UsMeterID uint32
1777 var DsMeterID uint32
1778
1779 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001780 formulateClassifierInfoFromFlow(classifierInfo, flow)
1781
1782 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1783 if err != nil {
1784 // Error logging is already done in the called function
1785 // So just return in case of error
1786 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301787 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001788
Esin Karamanccb714b2019-11-29 15:02:06 +00001789 if flows.HasGroup(flow) {
1790 // handle multicast flow
1791 f.handleFlowWithGroup(actionInfo, classifierInfo, flow)
1792 return
1793 }
1794
manikkaraj k17652a72019-05-06 09:06:36 -04001795 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001796 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1797 if err != nil {
1798 // error if any, already logged in the called function
1799 return
manikkaraj k17652a72019-05-06 09:06:36 -04001800 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001801
David K. Bainbridge82efc492019-09-04 09:57:11 -07001802 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1803 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001804
Humera Kouser94d7a842019-08-25 19:04:32 -04001805 if ethType, ok := classifierInfo[EthType]; ok {
1806 if ethType.(uint32) == LldpEthType {
1807 log.Info("Adding LLDP flow")
1808 f.addLLDPFlow(flow, portNo)
1809 return
1810 }
1811 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001812 if ipProto, ok := classifierInfo[IPProto]; ok {
1813 if ipProto.(uint32) == IPProtoDhcp {
1814 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301815 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001816 log.Debug("trap-dhcp-from-nni-flow")
1817 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1818 return
1819 }
1820 }
1821 }
1822 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001823 if isIgmpTrapDownstreamFlow(classifierInfo) {
1824 log.Debug("trap-igmp-from-nni-flow")
1825 f.addIgmpTrapFlowOnNNI(flow, classifierInfo, portNo)
1826 return
1827 }
A R Karthick1f85b802019-10-11 05:06:05 +00001828
1829 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301830 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001831
Chaitrashree G S90a17952019-11-14 21:51:21 -05001832 TpID, err := getTpIDFromFlow(flow)
1833 if err != nil {
1834 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1835 return
1836 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001837 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001838 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001839 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001840 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1841 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001842 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001843 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1844
1845 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301846
1847 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1848 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
1849 log.Debugw("no pending flows found, going ahead with flow install", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1850 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
1851 } else {
1852 ctx := context.Background()
1853 ctx, cancel := context.WithCancel(ctx)
1854 defer cancel()
1855 pendingFlowDelComplete := make(chan bool)
1856 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
1857 select {
1858 case <-pendingFlowDelComplete:
1859 log.Debugw("all pending flow deletes completed", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1860 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
1861
1862 case <-time.After(10 * time.Second):
1863 log.Errorw("pending flow deletes not completed after timeout", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1864 }
1865 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001866}
1867
Esin Karamanccb714b2019-11-29 15:02:06 +00001868// handleFlowWithGroup adds multicast flow to the device.
1869func (f *OpenOltFlowMgr) handleFlowWithGroup(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
1870 classifierInfo[PacketTagType] = DoubleTag
1871 log.Debugw("add-multicast-flow", log.Fields{"classifierInfo": classifierInfo, "actionInfo": actionInfo})
1872
1873 inPort, err := f.getInPortOfMulticastFlow(classifierInfo)
1874 if err != nil {
1875 log.Warnw("No inPort found. Ignoring multicast flow.", log.Fields{"flowId:": flow.Id})
1876 return
1877 }
1878 //replace ipDst with ethDst
1879 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
1880 flows.IsMulticastIp(ipv4Dst.(uint32)) {
1881 // replace ipv4_dst classifier with eth_dst
1882 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
1883 delete(classifierInfo, Ipv4Dst)
1884 delete(classifierInfo, EthType)
1885 classifierInfo[EthDst] = multicastMac
1886 log.Debugw("multicast-ip-to-mac-conversion-success", log.Fields{"ip:": ipv4Dst.(uint32), "mac:": multicastMac})
1887 }
1888
1889 var onuID = NoneOnuID
1890 var uniID = NoneUniID
1891 var gemPortID = NoneGemPortID
1892
1893 networkInterfaceID := IntfIDFromNniPortNum(inPort)
1894
1895 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
1896 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
1897 log.Debugw("multicast-flow-exists--not-re-adding", log.Fields{"classifierInfo": classifierInfo})
1898 return
1899 }
1900 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
1901 if err != nil {
1902 log.Errorw("Flow id unavailable for multicast flow", log.Fields{"error": err})
1903 return
1904 }
1905 var classifierProto *openoltpb2.Classifier
1906 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1907 log.Error("Error in making classifier protobuf for multicast flow")
1908 return
1909 }
1910 groupID := actionInfo[GroupID].(uint32)
1911 multicastFlow := openoltpb2.Flow{
1912 FlowId: flowID,
1913 FlowType: Multicast,
1914 NetworkIntfId: int32(networkInterfaceID),
1915 GroupId: groupID,
1916 Classifier: classifierProto,
1917 Priority: int32(flow.Priority),
1918 Cookie: flow.Cookie}
1919
1920 if ok := f.addFlowToDevice(flow, &multicastFlow); ok {
1921 log.Debug("multicast flow added to device successfully")
1922 //get cached group
1923 group, _, err := f.GetFlowGroupFromKVStore(groupID, true)
1924 if err == nil {
1925 //calling groupAdd to set group members after multicast flow creation
1926 if f.ModifyGroup(group) {
1927 //cached group can be removed now
1928 f.resourceMgr.RemoveFlowGroupFromKVStore(groupID, true)
1929 }
1930 }
1931
1932 flowsToKVStore := f.getUpdatedFlowInfo(&multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
1933 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1934 int32(onuID),
1935 int32(uniID),
1936 flowID, flowsToKVStore); err != nil {
1937 log.Errorw("Error uploading multicast flow into KV store", log.Fields{"flow": multicastFlow, "error": err})
1938 }
1939 }
1940 return
1941}
1942
1943//getInPortOfMulticastFlow return inPort criterion if exists; returns NNI interface of the device otherwise
1944func (f *OpenOltFlowMgr) getInPortOfMulticastFlow(classifierInfo map[string]interface{}) (uint32, error) {
1945 if _, ok := classifierInfo[InPort]; ok {
1946 return classifierInfo[InPort].(uint32), nil
1947 }
1948 // find first NNI port of the device
1949 nniPorts, e := f.resourceMgr.GetNNIFromKVStore()
1950 if e == nil && len(nniPorts) > 0 {
1951 return nniPorts[0], nil
1952 }
1953 return 0, errors.New("cannot find NNI port of device")
1954}
1955
1956// AddGroup add or update the group
1957func (f *OpenOltFlowMgr) AddGroup(group *ofp.OfpGroupEntry) {
1958 log.Infow("add-group", log.Fields{"group": group})
1959 if group == nil {
1960 log.Warn("skipping nil group")
1961 return
1962 }
1963
1964 groupToOlt := openoltpb2.Group{
1965 GroupId: group.Desc.GroupId,
1966 Command: openoltpb2.Group_SET_MEMBERS,
1967 Action: f.buildGroupAction(),
1968 }
1969
1970 log.Debugw("Sending group to device", log.Fields{"groupToOlt": groupToOlt})
1971 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), &groupToOlt)
1972 if err != nil {
1973 log.Errorw("add-group operation failed", log.Fields{"err": err, "groupToOlt": groupToOlt})
1974 return
1975 }
1976 // group members not created yet. So let's store the group
1977 if err := f.resourceMgr.AddFlowGroupToKVStore(group, true); err != nil {
1978 log.Errorw("Group cannot be stored in KV store", log.Fields{"groupId": group.Desc.GroupId, "err": err})
1979 } else {
1980 log.Debugw("add-group operation performed on the device successfully ", log.Fields{"groupToOlt": groupToOlt})
1981 }
1982}
1983
1984//buildGroupAction creates and returns a group action
1985func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
1986 var actionCmd openoltpb2.ActionCmd
1987 var action openoltpb2.Action
1988 action.Cmd = &actionCmd
1989 //pop outer vlan
1990 action.Cmd.RemoveOuterTag = true
1991 return &action
1992}
1993
1994// ModifyGroup updates the group
1995func (f *OpenOltFlowMgr) ModifyGroup(group *ofp.OfpGroupEntry) bool {
1996 log.Infow("modify-group", log.Fields{"group": group})
1997 if group == nil || group.Desc == nil {
1998 log.Warn("cannot modify group; group is nil")
1999 return false
2000 }
2001
2002 new := f.buildGroup(group.Desc.GroupId, group.Desc.Buckets)
2003 //get existing members of the group
2004 val, groupExists, err := f.GetFlowGroupFromKVStore(group.Desc.GroupId, false)
2005
2006 if err != nil {
2007 log.Errorw("Failed to retrieve the group from the store. Cannot modify group.",
2008 log.Fields{"groupId": group.Desc.GroupId, "err": err})
2009 return false
2010 }
2011
2012 var current *openoltpb2.Group
2013 if groupExists {
2014 // group already exists
2015 current = f.buildGroup(group.Desc.GroupId, val.Desc.GetBuckets())
2016 log.Debugw("modify-group: group exists.", log.Fields{"current": val, "new": group})
2017 } else {
2018 current = f.buildGroup(group.Desc.GroupId, nil)
2019 }
2020
2021 log.Debugw("modify-group: comparing current and new.", log.Fields{"current": current, "new": new})
2022 // check if the buckets are identical
2023 bucketsIdentical := f.bucketsIdentical(current, new)
2024
2025 isSuccess := true
2026 if !bucketsIdentical {
2027 groupToOlt := openoltpb2.Group{
2028 GroupId: group.Desc.GroupId,
2029 Command: openoltpb2.Group_SET_MEMBERS,
2030 Members: new.Members,
2031 Action: f.buildGroupAction(),
2032 }
2033
2034 if err := f.callGroupAdd(&groupToOlt); err != nil {
2035 log.Warnw("One of the group add/remove operations has failed. Cannot save group modifications",
2036 log.Fields{"group": group})
2037 isSuccess = false
2038 }
2039 }
2040
2041 if isSuccess {
2042 if err := f.resourceMgr.AddFlowGroupToKVStore(group, false); err != nil {
2043 log.Errorw("Failed to save the group into kv store", log.Fields{"groupId": group.Desc.GroupId})
2044 }
2045 log.Debugw("modify-group was success. Storing the group", log.Fields{"group": group, "existingGroup": current})
2046 }
2047 return isSuccess
2048}
2049
2050//bucketsIdentical returns true if groups are identical; false otherwise
2051func (f *OpenOltFlowMgr) bucketsIdentical(current *openoltpb2.Group, new *openoltpb2.Group) bool {
2052 if current.GroupId == new.GroupId &&
2053 len(new.Members) == len(current.Members) {
2054 diff := f.findDiff(current, new)
2055 if diff == nil || len(diff) < 1 {
2056 log.Infow("modify-group: current and new buckets are the same. Won't send SET_MEMBERS again.",
2057 log.Fields{"groupId:": current.GroupId})
2058 return true
2059 }
2060 }
2061 return false
2062}
2063
2064//findDiff compares group members and finds members which only exists in groups2
2065func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2066 var members []*openoltpb2.GroupMember
2067 for _, bucket := range group2.Members {
2068 if !f.contains(group1.Members, bucket) {
2069 // bucket does not exist and must be added
2070 members = append(members, bucket)
2071 }
2072 }
2073 return members
2074}
2075
2076//contains returns true if the members list contains the given member; false otherwise
2077func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2078 for _, groupMember := range members {
2079 if groupMember.InterfaceId == member.InterfaceId {
2080 return true
2081 }
2082 }
2083 return false
2084}
2085
2086//callGroupAdd call GroupAdd operation of openolt proto
2087func (f *OpenOltFlowMgr) callGroupAdd(group *openoltpb2.Group) error {
2088 log.Debugw("Sending group to device", log.Fields{"groupToOlt": group, "command": group.Command})
2089 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2090 if err != nil {
2091 log.Errorw("group operation failed", log.Fields{"err": err, "groupToOlt": group})
2092 }
2093 return err
2094}
2095
2096//buildGroup build openoltpb2.Group from given group id and bucket list
2097func (f *OpenOltFlowMgr) buildGroup(groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
2098 group := openoltpb2.Group{
2099 GroupId: groupID}
2100 // create members of the group
2101 if buckets != nil {
2102 for _, ofBucket := range buckets {
2103 member := f.buildMember(ofBucket)
2104 if member != nil && !f.contains(group.Members, member) {
2105 group.Members = append(group.Members, member)
2106 }
2107 }
2108 }
2109 return &group
2110}
2111
2112//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
2113func (f *OpenOltFlowMgr) buildMember(ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
2114 var outPort uint32
2115 outPortFound := false
2116 for _, ofAction := range ofBucket.Actions {
2117 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2118 outPort = ofAction.GetOutput().Port
2119 outPortFound = true
2120 }
2121 }
2122
2123 if !outPortFound {
2124 log.Debugw("bucket skipped since no out port found in it",
2125 log.Fields{"ofBucket": ofBucket})
2126 return nil
2127 }
2128 interfaceID := IntfIDFromUniPortNum(outPort)
2129 log.Debugw("got associated interface id of the port", log.Fields{"portNumber:": outPort, "interfaceId:": interfaceID})
2130 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2131 member := openoltpb2.GroupMember{
2132 InterfaceId: interfaceID,
2133 InterfaceType: openoltpb2.GroupMember_PON,
2134 GemPortId: groupInfo.gemPortID,
2135 Priority: groupInfo.servicePriority,
2136 }
2137 //add member to the group
2138 return &member
2139 }
2140 log.Warnf("bucket skipped since interface-2-gem mapping cannot be found",
2141 log.Fields{"ofBucket": ofBucket})
2142 return nil
2143}
2144
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002145//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04002146func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002147
2148 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302149 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002150 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05302151 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302152 }
Manikkaraj k884c1242019-04-11 16:26:42 +05302153 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04002154
Manikkaraj kb1d51442019-07-23 10:41:02 -04002155 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002156 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04002157 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
2158 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2159 tpDownloadMsg,
2160 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
2161 f.deviceHandler.deviceType,
2162 onuDevice.Type,
2163 onuDevice.Id,
2164 onuDevice.ProxyAddress.DeviceId, "")
2165 if sendErr != nil {
2166 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
2167 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
2168 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
2169 return sendErr
2170 }
2171 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302172 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302173}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002174
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302175//UpdateOnuInfo function adds onu info to cache and kvstore
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002176func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302177
2178 f.lockCache.Lock()
2179 defer f.lockCache.Unlock()
2180 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2181 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
2182 if err := f.resourceMgr.AddOnuInfo(intfID, onu); err != nil {
2183 log.Errorw("failed to add onu info", log.Fields{"onu": onu})
2184 return
2185 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002186 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
2187}
2188
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302189//addGemPortToOnuInfoMap function adds GEMport to ONU map
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002190func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302191 f.lockCache.Lock()
2192 defer f.lockCache.Unlock()
2193 onugem := f.onuGemInfo[intfID]
2194 // update the gem to the local cache as well as to kv strore
2195 for idx, onu := range onugem {
2196 if onu.OnuID == onuID {
2197 // check if gem already exists , else update the cache and kvstore
2198 for _, gem := range onu.GemPorts {
2199 if gem == gemPort {
2200 log.Debugw("Gem already in cache, no need to update cache and kv store",
2201 log.Fields{"gem": gemPort})
2202 return
2203 }
2204 }
2205 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2206 f.onuGemInfo[intfID] = onugem
2207 }
2208 }
2209 err := f.resourceMgr.AddGemToOnuGemInfo(intfID, onuID, gemPort)
2210 if err != nil {
2211 log.Errorw("Failed to add gem to onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002212 return
2213 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002214}
2215
2216// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002217
2218//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
2219func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302220
2221 f.lockCache.Lock()
2222 defer f.lockCache.Unlock()
2223
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002224 log.Debugw("Getting ONU ID from GEM port and PON port", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPortId": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302225 // get onuid from the onugem info cache
2226 onugem := f.onuGemInfo[intfID]
2227 for _, onu := range onugem {
2228 for _, gem := range onu.GemPorts {
2229 if gem == gemPortID {
2230 return onu.OnuID, nil
2231 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002232 }
2233 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002234 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
2235 return uint32(0), errors.New("key error, onuid is not found") // ONU ID 0 is not a valid one
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002236}
2237
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002238//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
2239func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002240 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002241 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002242 var err error
2243
2244 if packetIn.IntfType == "pon" {
2245 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002246 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002247 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
2248 return logicalPortNum, err
2249 }
2250 if packetIn.PortNo != 0 {
2251 logicalPortNum = packetIn.PortNo
2252 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002253 uniID := uint32(0) // FIXME - multi-uni support
2254 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002255 }
2256 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302257 f.UpdateGemPortForPktIn(packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002258 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002259 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002260 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08002261 log.Debugw("Retrieved logicalport from packet-in", log.Fields{
2262 "logicalPortNum": logicalPortNum,
2263 "IntfType": packetIn.IntfType,
2264 "packet": hex.EncodeToString(packetIn.Pkt),
2265 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002266 return logicalPortNum, nil
2267}
2268
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002269//GetPacketOutGemPortID returns gemPortId
2270func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
2271 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002272 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302273
2274 f.lockCache.Lock()
2275 defer f.lockCache.Unlock()
2276 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
2277
2278 gemPortID, ok := f.packetInGemPort[pktInkey]
2279 if ok {
2280 log.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
2281 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002282 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302283 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
2284 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(intfID, onuID, portNum)
2285 if err == nil {
2286 if gemPortID != 0 {
2287 f.packetInGemPort[pktInkey] = gemPortID
2288 log.Debugw("Found gem port from kv store and updating cache with gemport",
2289 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
2290 return gemPortID, nil
2291 }
2292 }
2293 log.Errorw("Failed to get gemport", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
2294 return uint32(0), err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002295}
2296
Manikkaraj kb1d51442019-07-23 10:41:02 -04002297func installFlowOnAllGemports(
2298 f1 func(intfId uint32, onuId uint32, uniId uint32,
2299 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
2300 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
2301 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302302 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
2303 classifier map[string]interface{}, action map[string]interface{}),
Manikkaraj kb1d51442019-07-23 10:41:02 -04002304 args map[string]uint32,
2305 classifier map[string]interface{}, action map[string]interface{},
2306 logicalFlow *ofp.OfpFlowStats,
2307 gemPorts []uint32,
2308 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00002309 vlanID ...uint32) {
2310 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
2311 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04002312 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002313 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002314 } else if FlowType == EapolFlow {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302315 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0], classifier, action)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002316 } else {
2317 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
2318 return
2319 }
2320 }
2321}
2322
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002323func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
2324 log.Debug("Adding trap-dhcp-of-nni-flow")
2325 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002326 classifier[PacketTagType] = DoubleTag
2327 action[TrapToHost] = true
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302328 var err error
2329 var networkInterfaceID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002330 /* We manage flowId resource pool on per PON port basis.
2331 Since this situation is tricky, as a hack, we pass the NNI port
2332 index (network_intf_id) as PON port Index for the flowId resource
2333 pool. Also, there is no ONU Id available for trapping DHCP packets
2334 on NNI port, use onu_id as -1 (invalid)
2335 ****************** CAVEAT *******************
2336 This logic works if the NNI Port Id falls within the same valid
2337 range of PON Port Ids. If this doesn't work for some OLT Vendor
2338 we need to have a re-look at this.
2339 *********************************************
2340 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002341 onuID := -1
2342 uniID := -1
2343 gemPortID := -1
2344 allocID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302345 networkInterfaceID, err = getNniIntfID(classifier, action)
2346 if err != nil {
2347 log.Error("Failed to get nniIntf ID")
2348 return
2349 }
2350
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002351 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302352 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002353 log.Debug("Flow-exists--not-re-adding")
2354 return
2355 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302356 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002357 if err != nil {
2358 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
2359 return
2360 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002361 var classifierProto *openoltpb2.Classifier
2362 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002363 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
2364 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
2365 return
2366 }
2367 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
2368 if actionProto = makeOpenOltActionField(action); actionProto == nil {
2369 log.Error("Error in making action protobuf for dhcp trap on nni flow")
2370 return
2371 }
2372 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002373 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2374 OnuId: int32(onuID), // OnuId not required
2375 UniId: int32(uniID), // UniId not used
2376 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002377 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002378 AllocId: int32(allocID), // AllocId not used
2379 NetworkIntfId: int32(networkInterfaceID),
2380 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002381 Classifier: classifierProto,
2382 Action: actionProto,
2383 Priority: int32(logicalFlow.Priority),
2384 Cookie: logicalFlow.Cookie,
2385 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002386 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002387 log.Debug("DHCP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302388 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002389 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
2390 int32(onuID),
2391 int32(uniID),
2392 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002393 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
2394 }
2395 }
2396 return
2397}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002398
Esin Karamanae41e2b2019-12-17 18:13:13 +00002399//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2400func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2401 var packetType string
2402 ovid, ivid := false, false
2403 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2404 vid := vlanID & VlanvIDMask
2405 if vid != ReservedVlan {
2406 ovid = true
2407 }
2408 }
2409 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2410 vid := uint32(metadata)
2411 if vid != ReservedVlan {
2412 ivid = true
2413 }
2414 }
2415 if ovid && ivid {
2416 packetType = DoubleTag
2417 } else if !ovid && !ivid {
2418 packetType = Untagged
2419 } else {
2420 packetType = SingleTag
2421 }
2422 return packetType
2423}
2424
2425//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
2426func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
2427 log.Debugw("Adding igmp-trap-of-nni-flow", log.Fields{"classifierInfo": classifier})
2428 action := make(map[string]interface{})
2429 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2430 action[TrapToHost] = true
2431 /* We manage flowId resource pool on per PON port basis.
2432 Since this situation is tricky, as a hack, we pass the NNI port
2433 index (network_intf_id) as PON port Index for the flowId resource
2434 pool. Also, there is no ONU Id available for trapping packets
2435 on NNI port, use onu_id as -1 (invalid)
2436 ****************** CAVEAT *******************
2437 This logic works if the NNI Port Id falls within the same valid
2438 range of PON Port Ids. If this doesn't work for some OLT Vendor
2439 we need to have a re-look at this.
2440 *********************************************
2441 */
2442 onuID := -1
2443 uniID := -1
2444 gemPortID := -1
2445 allocID := -1
2446 networkInterfaceID, err := getNniIntfID(classifier, action)
2447 if err != nil {
2448 log.Error("Failed to get nniIntf ID")
2449 return
2450 }
2451 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
2452 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
2453 log.Debug("igmp-flow-exists--not-re-adding")
2454 return
2455 }
2456 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
2457 if err != nil {
2458 log.Errorw("IGMP flow id unavailable for trap-on-NNI flow", log.Fields{"error": err})
2459 return
2460 }
2461 var classifierProto *openoltpb2.Classifier
2462 var actionProto *openoltpb2.Action
2463 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
2464 log.Error("Error in making classifier protobuf for igmp trap on nni flow")
2465 return
2466 }
2467 log.Debugw("Created classifier proto for the IGMP flow", log.Fields{"classifier": *classifierProto})
2468 if actionProto = makeOpenOltActionField(action); actionProto == nil {
2469 log.Error("Error in making action protobuf for IGMP trap on nni flow")
2470 return
2471 }
2472 log.Debugw("Created action proto for the IGMP flow", log.Fields{"action": *actionProto})
2473 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2474 OnuId: int32(onuID), // OnuId not required
2475 UniId: int32(uniID), // UniId not used
2476 FlowId: flowID,
2477 FlowType: Downstream,
2478 AllocId: int32(allocID), // AllocId not used
2479 NetworkIntfId: int32(networkInterfaceID),
2480 GemportId: int32(gemPortID), // GemportId not used
2481 Classifier: classifierProto,
2482 Action: actionProto,
2483 Priority: int32(logicalFlow.Priority),
2484 Cookie: logicalFlow.Cookie,
2485 PortNo: portNo}
2486 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
2487 log.Debug("IGMP Trap on NNI flow added to device successfully")
2488 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
2489 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
2490 int32(onuID),
2491 int32(uniID),
2492 flowID, flowsToKVStore); err != nil {
2493 log.Errorw("Error uploading igmp-trap-on-nni flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
2494 }
2495 }
2496 return
2497}
2498
salmansiddiqui7ac62132019-08-22 03:58:50 +00002499func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2500 if MeterID == 0 { // This should never happen
2501 log.Error("Invalid meter id")
2502 return "", errors.New("invalid meter id")
2503 }
2504 if Dir == tp_pb.Direction_UPSTREAM {
2505 return "upstream", nil
2506 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2507 return "downstream", nil
2508 }
2509 return "", nil
2510}
2511
2512func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00002513 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
2514 TpID uint32, uni string) {
2515 var gemPort uint32
2516 intfID := args[IntfID]
2517 onuID := args[OnuID]
2518 uniID := args[UniID]
2519 portNo := args[PortNo]
2520 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00002521 if ipProto, ok := classifierInfo[IPProto]; ok {
2522 if ipProto.(uint32) == IPProtoDhcp {
2523 log.Info("Adding DHCP flow")
2524 if pcp, ok := classifierInfo[VlanPcp]; ok {
2525 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2526 tp_pb.Direction_UPSTREAM,
2527 pcp.(uint32))
2528 //Adding DHCP upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00002529 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002530 } else {
2531 //Adding DHCP upstream flow to all gemports
2532 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
2533 }
2534
2535 } else if ipProto == IgmpProto {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002536 log.Infow("Adding Us IGMP flow", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "classifierInfo:": classifierInfo})
2537 if pcp, ok := classifierInfo[VlanPcp]; ok {
2538 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2539 tp_pb.Direction_UPSTREAM,
2540 pcp.(uint32))
2541 f.addIGMPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
2542 } else {
2543 //Adding IGMP upstream flow to all gem ports
2544 installFlowOnAllGemports(f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, IgmpFlow)
2545 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002546 } else {
2547 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
2548 return
2549 }
2550 } else if ethType, ok := classifierInfo[EthType]; ok {
2551 if ethType.(uint32) == EapEthType {
2552 log.Info("Adding EAPOL flow")
2553 var vlanID uint32
2554 if val, ok := classifierInfo[VlanVid]; ok {
2555 vlanID = (val.(uint32)) & VlanvIDMask
2556 } else {
2557 vlanID = DefaultMgmtVlan
2558 }
2559 if pcp, ok := classifierInfo[VlanPcp]; ok {
2560 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2561 tp_pb.Direction_UPSTREAM,
2562 pcp.(uint32))
2563
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302564 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID, gemPort, vlanID, classifierInfo, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002565 } else {
2566 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
2567 }
2568 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002569 } else if _, ok := actionInfo[PushVlan]; ok {
2570 log.Info("Adding upstream data rule")
2571 if pcp, ok := classifierInfo[VlanPcp]; ok {
2572 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2573 tp_pb.Direction_UPSTREAM,
2574 pcp.(uint32))
2575 //Adding HSIA upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00002576 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002577 } else {
2578 //Adding HSIA upstream flow to all gemports
2579 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
2580 }
2581 } else if _, ok := actionInfo[PopVlan]; ok {
2582 log.Info("Adding Downstream data rule")
2583 if pcp, ok := classifierInfo[VlanPcp]; ok {
2584 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05002585 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00002586 pcp.(uint32))
2587 //Adding HSIA downstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00002588 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002589 } else {
2590 //Adding HSIA downstream flow to all gemports
2591 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
2592 }
2593 } else {
2594 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
2595 return
2596 }
2597 // Send Techprofile download event to child device in go routine as it takes time
2598 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
2599}
2600
Gamze Abakafee36392019-10-03 11:17:24 +00002601func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
2602 flowIDList := f.flowsUsedByGemPort[gemPK]
2603 if len(flowIDList) > 1 {
2604 return true
2605 }
2606 return false
2607}
2608
Girish Gowdra54934262019-11-13 14:19:55 +05302609func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
Gamze Abakafee36392019-10-03 11:17:24 +00002610 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ponIntf, onuID, uniID)
2611 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2612 for _, currentGemPort := range currentGemPorts {
2613 for _, tpGemPort := range tpGemPorts {
2614 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2615 return true, currentGemPort
2616 }
2617 }
2618 }
Girish Gowdra54934262019-11-13 14:19:55 +05302619 if tpInst.InstanceCtrl.Onu == "single-instance" {
2620 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
2621 f.resourceMgr.RemoveTechProfileIDForOnu(ponIntf, uint32(onuID), uint32(uniID), tpID)
2622 f.DeleteTechProfileInstance(ponIntf, uint32(onuID), uint32(uniID), "", tpID)
2623
2624 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
2625 // still be used on other uni ports.
2626 // So, we need to check and make sure that no other gem port is referring to the given TP ID
2627 // on any other uni port.
2628 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(tpID, ponIntf, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302629 log.Debugw("got single instance tp instances", log.Fields{"tpInstances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302630 for i := 0; i < len(tpInstances); i++ {
2631 tpI := tpInstances[i]
2632 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05302633 for _, tpGemPort := range tpGemPorts {
2634 if tpGemPort.GemportID != gemPortID {
2635 log.Debugw("single instance tp is in use by gem", log.Fields{"gemPort": tpGemPort.GemportID})
2636 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05302637 }
2638 }
2639 }
2640 }
Girish Gowdra6b130582019-11-20 16:45:20 +05302641 log.Debug("tech profile is not in use by any gem")
Gamze Abakafee36392019-10-03 11:17:24 +00002642 return false, 0
2643}
2644
salmansiddiqui7ac62132019-08-22 03:58:50 +00002645func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002646 for _, field := range flows.GetOfbFields(flow) {
2647 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002648 classifierInfo[EthType] = field.GetEthType()
2649 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002650 } else if field.Type == flows.ETH_DST {
2651 classifierInfo[EthDst] = field.GetEthDst()
2652 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002653 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002654 classifierInfo[IPProto] = field.GetIpProto()
2655 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002656 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002657 classifierInfo[InPort] = field.GetPort()
2658 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002659 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302660 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00002661 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002662 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002663 classifierInfo[VlanPcp] = field.GetVlanPcp()
2664 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002665 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002666 classifierInfo[UDPDst] = field.GetUdpDst()
2667 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002668 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002669 classifierInfo[UDPSrc] = field.GetUdpSrc()
2670 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002671 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002672 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
2673 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002674 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002675 classifierInfo[Ipv4Src] = field.GetIpv4Src()
2676 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002677 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002678 classifierInfo[Metadata] = field.GetTableMetadata()
2679 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002680 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002681 classifierInfo[TunnelID] = field.GetTunnelId()
2682 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
2683 } else {
2684 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
2685 return
2686 }
2687 }
2688}
2689
2690func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002691 for _, action := range flows.GetActions(flow) {
2692 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002693 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002694 actionInfo[Output] = out.GetPort()
2695 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002696 } else {
2697 log.Error("Invalid output port in action")
2698 return errors.New("invalid output port in action")
2699 }
Scott Baker355d1742019-10-24 10:57:52 -07002700 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002701 actionInfo[PopVlan] = true
2702 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002703 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002704 if out := action.GetPush(); out != nil {
2705 if tpid := out.GetEthertype(); tpid != 0x8100 {
2706 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
2707 } else {
2708 actionInfo[PushVlan] = true
2709 actionInfo[TPID] = tpid
2710 log.Debugw("action-type-push-vlan",
2711 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
2712 }
2713 }
Scott Baker355d1742019-10-24 10:57:52 -07002714 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002715 if out := action.GetSetField(); out != nil {
2716 if field := out.GetField(); field != nil {
2717 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
2718 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
2719 return errors.New("invalid openflow class")
2720 }
2721 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
Esin Karamanccb714b2019-11-29 15:02:06 +00002722 formulateSetFieldActionInfoFromFlow(field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002723 }
2724 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002725 } else if action.Type == flows.GROUP {
2726 formulateGroupActionInfoFromFlow(action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002727 } else {
2728 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
2729 return errors.New("un supported action type")
2730 }
2731 }
2732 return nil
2733}
2734
Esin Karamanccb714b2019-11-29 15:02:06 +00002735func formulateSetFieldActionInfoFromFlow(field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
2736 if ofbField := field.GetOfbField(); ofbField != nil {
2737 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
2738 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2739 actionInfo[VlanVid] = vlan & 0xfff
2740 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
2741 } else {
2742 log.Error("No Invalid vlan id in set vlan-vid action")
2743 }
2744 } else {
2745 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
2746 }
2747 }
2748}
2749
2750func formulateGroupActionInfoFromFlow(action *ofp.OfpAction, actionInfo map[string]interface{}) {
2751 if action.GetGroup() == nil {
2752 log.Warn("No group entry found in the group action")
2753 } else {
2754 actionInfo[GroupID] = action.GetGroup().GroupId
2755 log.Debugw("action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
2756 }
2757}
2758
salmansiddiqui7ac62132019-08-22 03:58:50 +00002759func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002760 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002761 log.Debug("Controller bound trap flows, getting inport from tunnelid")
2762 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2763 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002764 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002765 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07002766 log.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 +00002767 } else {
2768 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
2769 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
2770 }
2771 }
2772 } else {
2773 log.Debug("Non-Controller flows, getting uniport from tunnelid")
2774 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07002775 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002776 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002777 actionInfo[Output] = uniPort
2778 log.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 +00002779 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002780 log.Debug("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002781 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
2782 }
2783 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2784 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002785 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002786 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07002787 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
2788 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002789 } else {
2790 log.Debug("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32),
David K. Bainbridge82efc492019-09-04 09:57:11 -07002791 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002792 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
2793 }
2794 }
2795 }
2796 return nil
2797}
Gamze Abakafee36392019-10-03 11:17:24 +00002798
Chaitrashree G S90a17952019-11-14 21:51:21 -05002799func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00002800 /* Metadata 8 bytes:
2801 Most Significant 2 Bytes = Inner VLAN
2802 Next 2 Bytes = Tech Profile ID(TPID)
2803 Least Significant 4 Bytes = Port ID
2804 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
2805 subscriber related flows.
2806 */
2807 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
2808 if metadata == 0 {
Chaitrashree G S90a17952019-11-14 21:51:21 -05002809 log.Error("metadata-is-not-present-in-flow-which-is-mandatory")
2810 return 0, errors.New("metadata-is-not-present-in-flow-which-is-mandatory")
Gamze Abakafee36392019-10-03 11:17:24 +00002811 }
2812 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002813 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00002814}
2815
2816func appendUnique(slice []uint32, item uint32) []uint32 {
2817 for _, sliceElement := range slice {
2818 if sliceElement == item {
2819 return slice
2820 }
2821 }
2822 return append(slice, item)
2823}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302824
2825// getNniIntfID gets nni intf id from the flow classifier/action
2826func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
2827
2828 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
2829 if portType == voltha.Port_PON_OLT {
2830 intfID := IntfIDFromNniPortNum(action[Output].(uint32))
2831 log.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
2832 return intfID, nil
2833 } else if portType == voltha.Port_ETHERNET_NNI {
2834 intfID := IntfIDFromNniPortNum(classifier[InPort].(uint32))
2835 log.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
2836 return intfID, nil
2837 }
2838 return uint32(0), nil
2839}
2840
2841// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
2842func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
2843 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
2844
2845 f.lockCache.Lock()
2846 defer f.lockCache.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05002847 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302848 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05002849 if lookupGemPort == gemPort {
2850 log.Debugw("pktin key/value found in cache , no need to update kv as we are assuming both will be in sync",
2851 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2852 return
2853 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302854 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05002855 f.packetInGemPort[pktInkey] = gemPort
2856
2857 f.resourceMgr.UpdateGemPortForPktIn(pktInkey, gemPort)
2858 log.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 +05302859 return
2860}
2861
2862// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
2863func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(intfID uint32, onuID uint32, portNum uint32) {
2864
2865 f.lockCache.Lock()
2866 defer f.lockCache.Unlock()
2867 onugem := f.onuGemInfo[intfID]
2868 for idx, onu := range onugem {
2869 if onu.OnuID == onuID {
2870 for _, uni := range onu.UniPorts {
2871 if uni == portNum {
2872 log.Debugw("uni already in cache, no need to update cache and kv store",
2873 log.Fields{"uni": portNum})
2874 return
2875 }
2876 }
2877 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
2878 f.onuGemInfo[intfID] = onugem
2879 }
2880 }
2881 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNum)
2882}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302883
2884func (f *OpenOltFlowMgr) loadFlowIDlistForGem(intf uint32) {
2885 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(intf)
2886 if err != nil {
2887 log.Error("Failed to get flowid list per gem", log.Fields{"intf": intf})
2888 return
2889 }
2890 for gem, FlowIDs := range flowIDsList {
2891 gemPK := gemPortKey{intf, uint32(gem)}
2892 f.flowsUsedByGemPort[gemPK] = FlowIDs
2893 }
2894 return
2895}
Esin Karamanccb714b2019-11-29 15:02:06 +00002896
2897//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
2898//and put them into interfaceToMcastQueueMap.
2899func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap() {
2900 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap()
2901 if err != nil {
2902 log.Error("Failed to get pon interface to multicast queue map")
2903 return
2904 }
2905 for intf, queueInfo := range storedMulticastQueueMap {
2906 q := queueInfoBrief{
2907 gemPortID: queueInfo[0],
2908 servicePriority: queueInfo[1],
2909 }
2910 f.interfaceToMcastQueueMap[intf] = &q
2911 }
2912}
2913
2914//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
2915//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
2916//Returns (nil, false, nil) if the group does not exists in the KV store.
2917func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
2918 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(groupID, cached)
2919 if err != nil {
2920 log.Errorw("Failed to get the flow group from KV store", log.Fields{"groupId": groupID, "err": err})
2921 return nil, false, errors.New("failed to retrieve the flow group")
2922 }
2923 if exists {
2924 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
2925 }
2926 return nil, exists, nil
2927}
2928
2929func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
2930 groupDesc := ofp.OfpGroupDesc{
2931 Type: ofp.OfpGroupType_OFPGT_ALL,
2932 GroupId: groupID,
2933 }
2934 groupEntry := ofp.OfpGroupEntry{
2935 Desc: &groupDesc,
2936 }
2937 var acts []*ofp.OfpAction
2938 for i := 0; i < len(outPorts); i++ {
2939 acts = append(acts, flows.Output(outPorts[i]))
2940 }
2941 bucket := ofp.OfpBucket{
2942 Actions: acts,
2943 }
2944 groupDesc.Buckets = []*ofp.OfpBucket{&bucket}
2945 return &groupEntry
2946}