blob: b8af453e2162c685d95582cd363d3e087b86970e [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
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301450//clearResources clears pon resources in kv store and the device
1451func (f *OpenOltFlowMgr) clearResources(flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
1452 gemPortID int32, flowID uint32, flowDirection string,
1453 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001454
Chaitrashree G S90a17952019-11-14 21:51:21 -05001455 tpID, err := getTpIDFromFlow(flow)
1456 if err != nil {
1457 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID})
1458 return err
1459 }
Gamze Abakafee36392019-10-03 11:17:24 +00001460
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001461 if len(updatedFlows) >= 0 {
1462 // There are still flows referencing the same flow_id.
1463 // So the flow should not be freed yet.
1464 // For ex: Case of HSIA where same flow is shared
1465 // between DS and US.
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301466 f.updateFlowInfoToKVStore(int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001467 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05301468 // Do this for subscriber flows only (not trap from NNI flows)
1469 if onuID != -1 && uniID != -1 {
1470 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1471 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
1472 log.Debugw("creating entry for pending flow delete",
1473 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1474 f.pendingFlowDelete.Store(pnFlDelKey, 1)
1475 } else {
1476 pnFlDels := val.(int) + 1
1477 log.Debugw("updating flow delete entry",
1478 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1479 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1480 }
1481
1482 defer f.deletePendingFlows(Intf, onuID, uniID)
1483 }
1484
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301485 log.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
1486 f.resourceMgr.FreeFlowID(Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001487
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301488 uni := getUniPortPath(Intf, onuID, uniID)
1489 tpPath := f.getTPpath(Intf, uni, tpID)
Gamze Abakafee36392019-10-03 11:17:24 +00001490 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301491 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(tpID, tpPath)
Gamze Abakafee36392019-10-03 11:17:24 +00001492 if err != nil { // This should not happen, something wrong in KV backend transaction
1493 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301494 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001495 }
1496 if techprofileInst == nil {
1497 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301498 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001499 }
1500
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301501 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001502 if f.isGemPortUsedByAnotherFlow(gemPK) {
1503 flowIDs := f.flowsUsedByGemPort[gemPK]
1504 for i, flowIDinMap := range flowIDs {
1505 if flowIDinMap == flowID {
1506 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301507 // everytime flowsUsedByGemPort cache is updated the same should be updated
1508 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001509 f.flowsUsedByGemPort[gemPK] = flowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301510 f.resourceMgr.UpdateFlowIDsForGem(Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00001511 break
1512 }
1513 }
1514 log.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301515 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001516 }
Gamze Abakafee36392019-10-03 11:17:24 +00001517 log.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301518 f.resourceMgr.RemoveGemPortIDForOnu(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001519 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1520 // 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 +05301521 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(uint32(gemPortID), Intf)
Gamze Abakafee36392019-10-03 11:17:24 +00001522 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301523 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1524 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001525 delete(f.flowsUsedByGemPort, gemPK)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301526 f.resourceMgr.DeleteFlowIDsForGem(Intf, uint32(gemPortID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301527 f.resourceMgr.FreeGemPortID(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001528 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05301529 // Delete the gem port on the ONU.
1530 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1531 log.Errorw("error processing delete gem-port towards onu",
1532 log.Fields{"err": err, "pon": Intf, "onuID": onuID, "uniID": uniID, "gemPortId": gemPortID})
1533 }
Gamze Abakafee36392019-10-03 11:17:24 +00001534
Girish Gowdra54934262019-11-13 14:19:55 +05301535 ok, _ := f.isTechProfileUsedByAnotherGem(Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001536 if !ok {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301537 f.resourceMgr.RemoveTechProfileIDForOnu(Intf, uint32(onuID), uint32(uniID), tpID)
1538 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1539 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1540 f.DeleteTechProfileInstance(Intf, uint32(onuID), uint32(uniID), "", tpID)
1541 f.resourceMgr.FreeAllocID(Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301542 // Delete the TCONT on the ONU.
1543 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
1544 log.Errorw("error processing delete tcont towards onu",
1545 log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID, "allocId": techprofileInst.UsScheduler.AllocID})
1546 }
Gamze Abakafee36392019-10-03 11:17:24 +00001547 }
1548 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001549 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301550 return nil
1551}
1552
1553func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowDirection string) {
1554
1555 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
Esin Karamanccb714b2019-11-29 15:02:06 +00001556
1557 if flowDirection == Multicast {
1558 f.clearMulticastFlowFromResourceManager(flow)
1559 return
1560 }
1561
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301562 var updatedFlows []rsrcMgr.FlowInfo
1563 var flowID uint32
1564 var onuID, uniID int32
1565 classifierInfo := make(map[string]interface{})
1566
1567 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1568 if err != nil {
1569 log.Error(err)
1570 return
1571 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301572
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301573 onuID = int32(onu)
1574 uniID = int32(uni)
1575
1576 for _, field := range flows.GetOfbFields(flow) {
1577 if field.Type == flows.IP_PROTO {
1578 classifierInfo[IPProto] = field.GetIpProto()
1579 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1580 }
1581 }
1582 log.Debugw("Extracted access info from flow to be deleted",
1583 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1584
1585 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1586 onuID = -1
1587 uniID = -1
1588 log.Debug("Trap on nni flow set oni, uni to -1")
1589 Intf = IntfIDFromNniPortNum(inPort)
1590 }
1591 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(Intf, onuID, uniID)
1592 for _, flowID = range flowIds {
1593 flowInfo := f.resourceMgr.GetFlowIDInfo(Intf, onuID, uniID, flowID)
1594 if flowInfo == nil {
1595 log.Debugw("No FlowInfo found found in KV store",
1596 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1597 return
1598 }
1599 updatedFlows = nil
1600 for _, flow := range *flowInfo {
1601 updatedFlows = append(updatedFlows, flow)
1602 }
1603
1604 for i, storedFlow := range updatedFlows {
1605 if flow.Id == storedFlow.LogicalFlowID {
1606 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1607 log.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
1608 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1609 log.Debug("Flow removed from device successfully")
1610 //Remove the Flow from FlowInfo
1611 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1612 err = f.clearResources(flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1613 flowID, flowDirection, portNum, updatedFlows)
1614 if err != nil {
1615 log.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
1616 return
1617 }
1618 } else {
1619 log.Error("Failed to remove flow from device")
1620 return
1621 }
1622 }
1623 }
1624 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001625}
1626
Esin Karamanccb714b2019-11-29 15:02:06 +00001627//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
1628// clears resources reserved for this multicast flow
1629func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(flow *ofp.OfpFlowStats) {
1630 classifierInfo := make(map[string]interface{})
1631 formulateClassifierInfoFromFlow(classifierInfo, flow)
1632 inPort, err := f.getInPortOfMulticastFlow(classifierInfo)
1633
1634 if err != nil {
1635 log.Warnw("No inPort found. Cannot release resources of the multicast flow.", log.Fields{"flowId:": flow.Id})
1636 return
1637 }
1638
1639 networkInterfaceID := IntfIDFromNniPortNum(inPort)
1640 var onuID = int32(NoneOnuID)
1641 var uniID = int32(NoneUniID)
1642 var flowID uint32
1643 var updatedFlows []rsrcMgr.FlowInfo
1644
1645 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(networkInterfaceID, onuID, uniID)
1646
1647 for _, flowID = range flowIds {
1648 flowInfo := f.resourceMgr.GetFlowIDInfo(networkInterfaceID, onuID, uniID, flowID)
1649 if flowInfo == nil {
1650 log.Debugw("No multicast FlowInfo found in the KV store",
1651 log.Fields{"Intf": networkInterfaceID, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1652 continue
1653 }
1654 updatedFlows = nil
1655 for _, flow := range *flowInfo {
1656 updatedFlows = append(updatedFlows, flow)
1657 }
1658 for i, storedFlow := range updatedFlows {
1659 if flow.Id == storedFlow.LogicalFlowID {
1660 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1661 log.Debugw("Multicast flow to be deleted", log.Fields{"flow": storedFlow})
1662 //remove from device
1663 if ok := f.removeFlowFromDevice(&removeFlowMessage); !ok {
1664 log.Errorw("Failed to remove multicast flow from device", log.Fields{"flowId": flow.Id})
1665 return
1666 }
1667 log.Debugw("Multicast flow removed from device successfully", log.Fields{"flowId": flow.Id})
1668 //Remove the Flow from FlowInfo
1669 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1670 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
1671 log.Error("Failed to delete multicast flow from the KV store", log.Fields{"flow": storedFlow, "err": err})
1672 return
1673 }
1674 //release flow id
1675 log.Debugw("Releasing multicast flow id", log.Fields{"flowId": flowID, "interfaceID": networkInterfaceID})
1676 f.resourceMgr.FreeFlowID(uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
1677 }
1678 }
1679 }
1680}
1681
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001682//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001683func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1684 log.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301685 var direction string
1686 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001687
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301688 for _, action := range flows.GetActions(flow) {
1689 if action.Type == flows.OUTPUT {
1690 if out := action.GetOutput(); out != nil {
1691 actionInfo[Output] = out.GetPort()
1692 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
1693 } else {
1694 log.Error("Invalid output port in action")
1695 return
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001696 }
1697 }
1698 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001699
1700 if flows.HasGroup(flow) {
1701 direction = Multicast
1702 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301703 direction = Upstream
1704 } else {
1705 direction = Downstream
1706 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301707 f.clearFlowFromResourceManager(flow, direction) //TODO: Take care of the limitations
1708
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001709 return
1710}
1711
Girish Gowdra3d633032019-12-10 16:37:05 +05301712func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
1713 uniID uint32, ch chan bool) {
1714 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1715 for {
1716 select {
1717 case <-time.After(20 * time.Millisecond):
1718 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
1719 log.Debug("pending flow deletes completed")
1720 ch <- true
1721 return
1722 }
1723 case <-ctx.Done():
1724 log.Error("flow delete wait handler routine canceled")
1725 return
1726 }
1727 }
1728}
1729
Esin Karamanae41e2b2019-12-17 18:13:13 +00001730//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
1731func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
1732 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
1733 if ethType, ok := classifierInfo[EthType]; ok {
1734 if ethType.(uint32) == IPv4EthType {
1735 if ipProto, ok := classifierInfo[IPProto]; ok {
1736 if ipProto.(uint32) == IgmpProto {
1737 return true
1738 }
1739 }
1740 }
1741 }
1742 }
1743 return false
1744}
1745
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001746// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301747// nolint: gocyclo
Manikkaraj kb1d51442019-07-23 10:41:02 -04001748func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001749 classifierInfo := make(map[string]interface{})
1750 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001751 var UsMeterID uint32
1752 var DsMeterID uint32
1753
1754 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001755 formulateClassifierInfoFromFlow(classifierInfo, flow)
1756
1757 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1758 if err != nil {
1759 // Error logging is already done in the called function
1760 // So just return in case of error
1761 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301762 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001763
Esin Karamanccb714b2019-11-29 15:02:06 +00001764 if flows.HasGroup(flow) {
1765 // handle multicast flow
1766 f.handleFlowWithGroup(actionInfo, classifierInfo, flow)
1767 return
1768 }
1769
manikkaraj k17652a72019-05-06 09:06:36 -04001770 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001771 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1772 if err != nil {
1773 // error if any, already logged in the called function
1774 return
manikkaraj k17652a72019-05-06 09:06:36 -04001775 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001776
David K. Bainbridge82efc492019-09-04 09:57:11 -07001777 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1778 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001779
Humera Kouser94d7a842019-08-25 19:04:32 -04001780 if ethType, ok := classifierInfo[EthType]; ok {
1781 if ethType.(uint32) == LldpEthType {
1782 log.Info("Adding LLDP flow")
1783 f.addLLDPFlow(flow, portNo)
1784 return
1785 }
1786 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001787 if ipProto, ok := classifierInfo[IPProto]; ok {
1788 if ipProto.(uint32) == IPProtoDhcp {
1789 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301790 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001791 log.Debug("trap-dhcp-from-nni-flow")
1792 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1793 return
1794 }
1795 }
1796 }
1797 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001798 if isIgmpTrapDownstreamFlow(classifierInfo) {
1799 log.Debug("trap-igmp-from-nni-flow")
1800 f.addIgmpTrapFlowOnNNI(flow, classifierInfo, portNo)
1801 return
1802 }
A R Karthick1f85b802019-10-11 05:06:05 +00001803
1804 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301805 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001806
Chaitrashree G S90a17952019-11-14 21:51:21 -05001807 TpID, err := getTpIDFromFlow(flow)
1808 if err != nil {
1809 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1810 return
1811 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001812 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001813 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001814 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001815 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1816 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001817 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001818 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1819
1820 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301821
1822 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1823 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
1824 log.Debugw("no pending flows found, going ahead with flow install", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1825 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
1826 } else {
1827 ctx := context.Background()
1828 ctx, cancel := context.WithCancel(ctx)
1829 defer cancel()
1830 pendingFlowDelComplete := make(chan bool)
1831 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
1832 select {
1833 case <-pendingFlowDelComplete:
1834 log.Debugw("all pending flow deletes completed", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1835 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
1836
1837 case <-time.After(10 * time.Second):
1838 log.Errorw("pending flow deletes not completed after timeout", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1839 }
1840 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001841}
1842
Esin Karamanccb714b2019-11-29 15:02:06 +00001843// handleFlowWithGroup adds multicast flow to the device.
1844func (f *OpenOltFlowMgr) handleFlowWithGroup(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
1845 classifierInfo[PacketTagType] = DoubleTag
1846 log.Debugw("add-multicast-flow", log.Fields{"classifierInfo": classifierInfo, "actionInfo": actionInfo})
1847
1848 inPort, err := f.getInPortOfMulticastFlow(classifierInfo)
1849 if err != nil {
1850 log.Warnw("No inPort found. Ignoring multicast flow.", log.Fields{"flowId:": flow.Id})
1851 return
1852 }
1853 //replace ipDst with ethDst
1854 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
1855 flows.IsMulticastIp(ipv4Dst.(uint32)) {
1856 // replace ipv4_dst classifier with eth_dst
1857 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
1858 delete(classifierInfo, Ipv4Dst)
1859 delete(classifierInfo, EthType)
1860 classifierInfo[EthDst] = multicastMac
1861 log.Debugw("multicast-ip-to-mac-conversion-success", log.Fields{"ip:": ipv4Dst.(uint32), "mac:": multicastMac})
1862 }
1863
1864 var onuID = NoneOnuID
1865 var uniID = NoneUniID
1866 var gemPortID = NoneGemPortID
1867
1868 networkInterfaceID := IntfIDFromNniPortNum(inPort)
1869
1870 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
1871 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
1872 log.Debugw("multicast-flow-exists--not-re-adding", log.Fields{"classifierInfo": classifierInfo})
1873 return
1874 }
1875 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
1876 if err != nil {
1877 log.Errorw("Flow id unavailable for multicast flow", log.Fields{"error": err})
1878 return
1879 }
1880 var classifierProto *openoltpb2.Classifier
1881 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1882 log.Error("Error in making classifier protobuf for multicast flow")
1883 return
1884 }
1885 groupID := actionInfo[GroupID].(uint32)
1886 multicastFlow := openoltpb2.Flow{
1887 FlowId: flowID,
1888 FlowType: Multicast,
1889 NetworkIntfId: int32(networkInterfaceID),
1890 GroupId: groupID,
1891 Classifier: classifierProto,
1892 Priority: int32(flow.Priority),
1893 Cookie: flow.Cookie}
1894
1895 if ok := f.addFlowToDevice(flow, &multicastFlow); ok {
1896 log.Debug("multicast flow added to device successfully")
1897 //get cached group
1898 group, _, err := f.GetFlowGroupFromKVStore(groupID, true)
1899 if err == nil {
1900 //calling groupAdd to set group members after multicast flow creation
1901 if f.ModifyGroup(group) {
1902 //cached group can be removed now
1903 f.resourceMgr.RemoveFlowGroupFromKVStore(groupID, true)
1904 }
1905 }
1906
1907 flowsToKVStore := f.getUpdatedFlowInfo(&multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
1908 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1909 int32(onuID),
1910 int32(uniID),
1911 flowID, flowsToKVStore); err != nil {
1912 log.Errorw("Error uploading multicast flow into KV store", log.Fields{"flow": multicastFlow, "error": err})
1913 }
1914 }
1915 return
1916}
1917
1918//getInPortOfMulticastFlow return inPort criterion if exists; returns NNI interface of the device otherwise
1919func (f *OpenOltFlowMgr) getInPortOfMulticastFlow(classifierInfo map[string]interface{}) (uint32, error) {
1920 if _, ok := classifierInfo[InPort]; ok {
1921 return classifierInfo[InPort].(uint32), nil
1922 }
1923 // find first NNI port of the device
1924 nniPorts, e := f.resourceMgr.GetNNIFromKVStore()
1925 if e == nil && len(nniPorts) > 0 {
1926 return nniPorts[0], nil
1927 }
1928 return 0, errors.New("cannot find NNI port of device")
1929}
1930
1931// AddGroup add or update the group
1932func (f *OpenOltFlowMgr) AddGroup(group *ofp.OfpGroupEntry) {
1933 log.Infow("add-group", log.Fields{"group": group})
1934 if group == nil {
1935 log.Warn("skipping nil group")
1936 return
1937 }
1938
1939 groupToOlt := openoltpb2.Group{
1940 GroupId: group.Desc.GroupId,
1941 Command: openoltpb2.Group_SET_MEMBERS,
1942 Action: f.buildGroupAction(),
1943 }
1944
1945 log.Debugw("Sending group to device", log.Fields{"groupToOlt": groupToOlt})
1946 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), &groupToOlt)
1947 if err != nil {
1948 log.Errorw("add-group operation failed", log.Fields{"err": err, "groupToOlt": groupToOlt})
1949 return
1950 }
1951 // group members not created yet. So let's store the group
1952 if err := f.resourceMgr.AddFlowGroupToKVStore(group, true); err != nil {
1953 log.Errorw("Group cannot be stored in KV store", log.Fields{"groupId": group.Desc.GroupId, "err": err})
1954 } else {
1955 log.Debugw("add-group operation performed on the device successfully ", log.Fields{"groupToOlt": groupToOlt})
1956 }
1957}
1958
1959//buildGroupAction creates and returns a group action
1960func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
1961 var actionCmd openoltpb2.ActionCmd
1962 var action openoltpb2.Action
1963 action.Cmd = &actionCmd
1964 //pop outer vlan
1965 action.Cmd.RemoveOuterTag = true
1966 return &action
1967}
1968
1969// ModifyGroup updates the group
1970func (f *OpenOltFlowMgr) ModifyGroup(group *ofp.OfpGroupEntry) bool {
1971 log.Infow("modify-group", log.Fields{"group": group})
1972 if group == nil || group.Desc == nil {
1973 log.Warn("cannot modify group; group is nil")
1974 return false
1975 }
1976
1977 new := f.buildGroup(group.Desc.GroupId, group.Desc.Buckets)
1978 //get existing members of the group
1979 val, groupExists, err := f.GetFlowGroupFromKVStore(group.Desc.GroupId, false)
1980
1981 if err != nil {
1982 log.Errorw("Failed to retrieve the group from the store. Cannot modify group.",
1983 log.Fields{"groupId": group.Desc.GroupId, "err": err})
1984 return false
1985 }
1986
1987 var current *openoltpb2.Group
1988 if groupExists {
1989 // group already exists
1990 current = f.buildGroup(group.Desc.GroupId, val.Desc.GetBuckets())
1991 log.Debugw("modify-group: group exists.", log.Fields{"current": val, "new": group})
1992 } else {
1993 current = f.buildGroup(group.Desc.GroupId, nil)
1994 }
1995
1996 log.Debugw("modify-group: comparing current and new.", log.Fields{"current": current, "new": new})
1997 // check if the buckets are identical
1998 bucketsIdentical := f.bucketsIdentical(current, new)
1999
2000 isSuccess := true
2001 if !bucketsIdentical {
2002 groupToOlt := openoltpb2.Group{
2003 GroupId: group.Desc.GroupId,
2004 Command: openoltpb2.Group_SET_MEMBERS,
2005 Members: new.Members,
2006 Action: f.buildGroupAction(),
2007 }
2008
2009 if err := f.callGroupAdd(&groupToOlt); err != nil {
2010 log.Warnw("One of the group add/remove operations has failed. Cannot save group modifications",
2011 log.Fields{"group": group})
2012 isSuccess = false
2013 }
2014 }
2015
2016 if isSuccess {
2017 if err := f.resourceMgr.AddFlowGroupToKVStore(group, false); err != nil {
2018 log.Errorw("Failed to save the group into kv store", log.Fields{"groupId": group.Desc.GroupId})
2019 }
2020 log.Debugw("modify-group was success. Storing the group", log.Fields{"group": group, "existingGroup": current})
2021 }
2022 return isSuccess
2023}
2024
2025//bucketsIdentical returns true if groups are identical; false otherwise
2026func (f *OpenOltFlowMgr) bucketsIdentical(current *openoltpb2.Group, new *openoltpb2.Group) bool {
2027 if current.GroupId == new.GroupId &&
2028 len(new.Members) == len(current.Members) {
2029 diff := f.findDiff(current, new)
2030 if diff == nil || len(diff) < 1 {
2031 log.Infow("modify-group: current and new buckets are the same. Won't send SET_MEMBERS again.",
2032 log.Fields{"groupId:": current.GroupId})
2033 return true
2034 }
2035 }
2036 return false
2037}
2038
2039//findDiff compares group members and finds members which only exists in groups2
2040func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2041 var members []*openoltpb2.GroupMember
2042 for _, bucket := range group2.Members {
2043 if !f.contains(group1.Members, bucket) {
2044 // bucket does not exist and must be added
2045 members = append(members, bucket)
2046 }
2047 }
2048 return members
2049}
2050
2051//contains returns true if the members list contains the given member; false otherwise
2052func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2053 for _, groupMember := range members {
2054 if groupMember.InterfaceId == member.InterfaceId {
2055 return true
2056 }
2057 }
2058 return false
2059}
2060
2061//callGroupAdd call GroupAdd operation of openolt proto
2062func (f *OpenOltFlowMgr) callGroupAdd(group *openoltpb2.Group) error {
2063 log.Debugw("Sending group to device", log.Fields{"groupToOlt": group, "command": group.Command})
2064 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2065 if err != nil {
2066 log.Errorw("group operation failed", log.Fields{"err": err, "groupToOlt": group})
2067 }
2068 return err
2069}
2070
2071//buildGroup build openoltpb2.Group from given group id and bucket list
2072func (f *OpenOltFlowMgr) buildGroup(groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
2073 group := openoltpb2.Group{
2074 GroupId: groupID}
2075 // create members of the group
2076 if buckets != nil {
2077 for _, ofBucket := range buckets {
2078 member := f.buildMember(ofBucket)
2079 if member != nil && !f.contains(group.Members, member) {
2080 group.Members = append(group.Members, member)
2081 }
2082 }
2083 }
2084 return &group
2085}
2086
2087//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
2088func (f *OpenOltFlowMgr) buildMember(ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
2089 var outPort uint32
2090 outPortFound := false
2091 for _, ofAction := range ofBucket.Actions {
2092 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2093 outPort = ofAction.GetOutput().Port
2094 outPortFound = true
2095 }
2096 }
2097
2098 if !outPortFound {
2099 log.Debugw("bucket skipped since no out port found in it",
2100 log.Fields{"ofBucket": ofBucket})
2101 return nil
2102 }
2103 interfaceID := IntfIDFromUniPortNum(outPort)
2104 log.Debugw("got associated interface id of the port", log.Fields{"portNumber:": outPort, "interfaceId:": interfaceID})
2105 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2106 member := openoltpb2.GroupMember{
2107 InterfaceId: interfaceID,
2108 InterfaceType: openoltpb2.GroupMember_PON,
2109 GemPortId: groupInfo.gemPortID,
2110 Priority: groupInfo.servicePriority,
2111 }
2112 //add member to the group
2113 return &member
2114 }
2115 log.Warnf("bucket skipped since interface-2-gem mapping cannot be found",
2116 log.Fields{"ofBucket": ofBucket})
2117 return nil
2118}
2119
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002120//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04002121func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002122
2123 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302124 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002125 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05302126 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302127 }
Manikkaraj k884c1242019-04-11 16:26:42 +05302128 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04002129
Manikkaraj kb1d51442019-07-23 10:41:02 -04002130 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002131 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04002132 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
2133 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2134 tpDownloadMsg,
2135 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
2136 f.deviceHandler.deviceType,
2137 onuDevice.Type,
2138 onuDevice.Id,
2139 onuDevice.ProxyAddress.DeviceId, "")
2140 if sendErr != nil {
2141 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
2142 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
2143 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
2144 return sendErr
2145 }
2146 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302147 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302148}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002149
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302150//UpdateOnuInfo function adds onu info to cache and kvstore
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002151func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302152
2153 f.lockCache.Lock()
2154 defer f.lockCache.Unlock()
2155 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2156 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
2157 if err := f.resourceMgr.AddOnuInfo(intfID, onu); err != nil {
2158 log.Errorw("failed to add onu info", log.Fields{"onu": onu})
2159 return
2160 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002161 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
2162}
2163
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302164//addGemPortToOnuInfoMap function adds GEMport to ONU map
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002165func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302166 f.lockCache.Lock()
2167 defer f.lockCache.Unlock()
2168 onugem := f.onuGemInfo[intfID]
2169 // update the gem to the local cache as well as to kv strore
2170 for idx, onu := range onugem {
2171 if onu.OnuID == onuID {
2172 // check if gem already exists , else update the cache and kvstore
2173 for _, gem := range onu.GemPorts {
2174 if gem == gemPort {
2175 log.Debugw("Gem already in cache, no need to update cache and kv store",
2176 log.Fields{"gem": gemPort})
2177 return
2178 }
2179 }
2180 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2181 f.onuGemInfo[intfID] = onugem
2182 }
2183 }
2184 err := f.resourceMgr.AddGemToOnuGemInfo(intfID, onuID, gemPort)
2185 if err != nil {
2186 log.Errorw("Failed to add gem to onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002187 return
2188 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002189}
2190
2191// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002192
2193//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
2194func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302195
2196 f.lockCache.Lock()
2197 defer f.lockCache.Unlock()
2198
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002199 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 +05302200 // get onuid from the onugem info cache
2201 onugem := f.onuGemInfo[intfID]
2202 for _, onu := range onugem {
2203 for _, gem := range onu.GemPorts {
2204 if gem == gemPortID {
2205 return onu.OnuID, nil
2206 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002207 }
2208 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002209 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
2210 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 -04002211}
2212
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002213//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
2214func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002215 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002216 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002217 var err error
2218
2219 if packetIn.IntfType == "pon" {
2220 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002221 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002222 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
2223 return logicalPortNum, err
2224 }
2225 if packetIn.PortNo != 0 {
2226 logicalPortNum = packetIn.PortNo
2227 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002228 uniID := uint32(0) // FIXME - multi-uni support
2229 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002230 }
2231 // 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 +05302232 f.UpdateGemPortForPktIn(packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002233 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002234 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002235 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08002236 log.Debugw("Retrieved logicalport from packet-in", log.Fields{
2237 "logicalPortNum": logicalPortNum,
2238 "IntfType": packetIn.IntfType,
2239 "packet": hex.EncodeToString(packetIn.Pkt),
2240 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002241 return logicalPortNum, nil
2242}
2243
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002244//GetPacketOutGemPortID returns gemPortId
2245func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
2246 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002247 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302248
2249 f.lockCache.Lock()
2250 defer f.lockCache.Unlock()
2251 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
2252
2253 gemPortID, ok := f.packetInGemPort[pktInkey]
2254 if ok {
2255 log.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
2256 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002257 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302258 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
2259 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(intfID, onuID, portNum)
2260 if err == nil {
2261 if gemPortID != 0 {
2262 f.packetInGemPort[pktInkey] = gemPortID
2263 log.Debugw("Found gem port from kv store and updating cache with gemport",
2264 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
2265 return gemPortID, nil
2266 }
2267 }
2268 log.Errorw("Failed to get gemport", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
2269 return uint32(0), err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002270}
2271
Manikkaraj kb1d51442019-07-23 10:41:02 -04002272func installFlowOnAllGemports(
2273 f1 func(intfId uint32, onuId uint32, uniId uint32,
2274 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
2275 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
2276 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302277 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
2278 classifier map[string]interface{}, action map[string]interface{}),
Manikkaraj kb1d51442019-07-23 10:41:02 -04002279 args map[string]uint32,
2280 classifier map[string]interface{}, action map[string]interface{},
2281 logicalFlow *ofp.OfpFlowStats,
2282 gemPorts []uint32,
2283 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00002284 vlanID ...uint32) {
2285 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
2286 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04002287 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002288 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002289 } else if FlowType == EapolFlow {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302290 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0], classifier, action)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002291 } else {
2292 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
2293 return
2294 }
2295 }
2296}
2297
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002298func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
2299 log.Debug("Adding trap-dhcp-of-nni-flow")
2300 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002301 classifier[PacketTagType] = DoubleTag
2302 action[TrapToHost] = true
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302303 var err error
2304 var networkInterfaceID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002305 /* We manage flowId resource pool on per PON port basis.
2306 Since this situation is tricky, as a hack, we pass the NNI port
2307 index (network_intf_id) as PON port Index for the flowId resource
2308 pool. Also, there is no ONU Id available for trapping DHCP packets
2309 on NNI port, use onu_id as -1 (invalid)
2310 ****************** CAVEAT *******************
2311 This logic works if the NNI Port Id falls within the same valid
2312 range of PON Port Ids. If this doesn't work for some OLT Vendor
2313 we need to have a re-look at this.
2314 *********************************************
2315 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002316 onuID := -1
2317 uniID := -1
2318 gemPortID := -1
2319 allocID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302320 networkInterfaceID, err = getNniIntfID(classifier, action)
2321 if err != nil {
2322 log.Error("Failed to get nniIntf ID")
2323 return
2324 }
2325
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002326 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302327 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002328 log.Debug("Flow-exists--not-re-adding")
2329 return
2330 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302331 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002332 if err != nil {
2333 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
2334 return
2335 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002336 var classifierProto *openoltpb2.Classifier
2337 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002338 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
2339 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
2340 return
2341 }
2342 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
2343 if actionProto = makeOpenOltActionField(action); actionProto == nil {
2344 log.Error("Error in making action protobuf for dhcp trap on nni flow")
2345 return
2346 }
2347 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002348 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2349 OnuId: int32(onuID), // OnuId not required
2350 UniId: int32(uniID), // UniId not used
2351 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002352 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002353 AllocId: int32(allocID), // AllocId not used
2354 NetworkIntfId: int32(networkInterfaceID),
2355 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002356 Classifier: classifierProto,
2357 Action: actionProto,
2358 Priority: int32(logicalFlow.Priority),
2359 Cookie: logicalFlow.Cookie,
2360 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002361 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002362 log.Debug("DHCP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302363 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002364 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
2365 int32(onuID),
2366 int32(uniID),
2367 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002368 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
2369 }
2370 }
2371 return
2372}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002373
Esin Karamanae41e2b2019-12-17 18:13:13 +00002374//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2375func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2376 var packetType string
2377 ovid, ivid := false, false
2378 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2379 vid := vlanID & VlanvIDMask
2380 if vid != ReservedVlan {
2381 ovid = true
2382 }
2383 }
2384 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2385 vid := uint32(metadata)
2386 if vid != ReservedVlan {
2387 ivid = true
2388 }
2389 }
2390 if ovid && ivid {
2391 packetType = DoubleTag
2392 } else if !ovid && !ivid {
2393 packetType = Untagged
2394 } else {
2395 packetType = SingleTag
2396 }
2397 return packetType
2398}
2399
2400//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
2401func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
2402 log.Debugw("Adding igmp-trap-of-nni-flow", log.Fields{"classifierInfo": classifier})
2403 action := make(map[string]interface{})
2404 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2405 action[TrapToHost] = true
2406 /* We manage flowId resource pool on per PON port basis.
2407 Since this situation is tricky, as a hack, we pass the NNI port
2408 index (network_intf_id) as PON port Index for the flowId resource
2409 pool. Also, there is no ONU Id available for trapping packets
2410 on NNI port, use onu_id as -1 (invalid)
2411 ****************** CAVEAT *******************
2412 This logic works if the NNI Port Id falls within the same valid
2413 range of PON Port Ids. If this doesn't work for some OLT Vendor
2414 we need to have a re-look at this.
2415 *********************************************
2416 */
2417 onuID := -1
2418 uniID := -1
2419 gemPortID := -1
2420 allocID := -1
2421 networkInterfaceID, err := getNniIntfID(classifier, action)
2422 if err != nil {
2423 log.Error("Failed to get nniIntf ID")
2424 return
2425 }
2426 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
2427 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
2428 log.Debug("igmp-flow-exists--not-re-adding")
2429 return
2430 }
2431 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
2432 if err != nil {
2433 log.Errorw("IGMP flow id unavailable for trap-on-NNI flow", log.Fields{"error": err})
2434 return
2435 }
2436 var classifierProto *openoltpb2.Classifier
2437 var actionProto *openoltpb2.Action
2438 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
2439 log.Error("Error in making classifier protobuf for igmp trap on nni flow")
2440 return
2441 }
2442 log.Debugw("Created classifier proto for the IGMP flow", log.Fields{"classifier": *classifierProto})
2443 if actionProto = makeOpenOltActionField(action); actionProto == nil {
2444 log.Error("Error in making action protobuf for IGMP trap on nni flow")
2445 return
2446 }
2447 log.Debugw("Created action proto for the IGMP flow", log.Fields{"action": *actionProto})
2448 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2449 OnuId: int32(onuID), // OnuId not required
2450 UniId: int32(uniID), // UniId not used
2451 FlowId: flowID,
2452 FlowType: Downstream,
2453 AllocId: int32(allocID), // AllocId not used
2454 NetworkIntfId: int32(networkInterfaceID),
2455 GemportId: int32(gemPortID), // GemportId not used
2456 Classifier: classifierProto,
2457 Action: actionProto,
2458 Priority: int32(logicalFlow.Priority),
2459 Cookie: logicalFlow.Cookie,
2460 PortNo: portNo}
2461 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
2462 log.Debug("IGMP Trap on NNI flow added to device successfully")
2463 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
2464 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
2465 int32(onuID),
2466 int32(uniID),
2467 flowID, flowsToKVStore); err != nil {
2468 log.Errorw("Error uploading igmp-trap-on-nni flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
2469 }
2470 }
2471 return
2472}
2473
salmansiddiqui7ac62132019-08-22 03:58:50 +00002474func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2475 if MeterID == 0 { // This should never happen
2476 log.Error("Invalid meter id")
2477 return "", errors.New("invalid meter id")
2478 }
2479 if Dir == tp_pb.Direction_UPSTREAM {
2480 return "upstream", nil
2481 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2482 return "downstream", nil
2483 }
2484 return "", nil
2485}
2486
2487func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00002488 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
2489 TpID uint32, uni string) {
2490 var gemPort uint32
2491 intfID := args[IntfID]
2492 onuID := args[OnuID]
2493 uniID := args[UniID]
2494 portNo := args[PortNo]
2495 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00002496 if ipProto, ok := classifierInfo[IPProto]; ok {
2497 if ipProto.(uint32) == IPProtoDhcp {
2498 log.Info("Adding DHCP flow")
2499 if pcp, ok := classifierInfo[VlanPcp]; ok {
2500 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2501 tp_pb.Direction_UPSTREAM,
2502 pcp.(uint32))
2503 //Adding DHCP upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00002504 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002505 } else {
2506 //Adding DHCP upstream flow to all gemports
2507 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
2508 }
2509
2510 } else if ipProto == IgmpProto {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002511 log.Infow("Adding Us IGMP flow", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "classifierInfo:": classifierInfo})
2512 if pcp, ok := classifierInfo[VlanPcp]; ok {
2513 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2514 tp_pb.Direction_UPSTREAM,
2515 pcp.(uint32))
2516 f.addIGMPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
2517 } else {
2518 //Adding IGMP upstream flow to all gem ports
2519 installFlowOnAllGemports(f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, IgmpFlow)
2520 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002521 } else {
2522 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
2523 return
2524 }
2525 } else if ethType, ok := classifierInfo[EthType]; ok {
2526 if ethType.(uint32) == EapEthType {
2527 log.Info("Adding EAPOL flow")
2528 var vlanID uint32
2529 if val, ok := classifierInfo[VlanVid]; ok {
2530 vlanID = (val.(uint32)) & VlanvIDMask
2531 } else {
2532 vlanID = DefaultMgmtVlan
2533 }
2534 if pcp, ok := classifierInfo[VlanPcp]; ok {
2535 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2536 tp_pb.Direction_UPSTREAM,
2537 pcp.(uint32))
2538
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302539 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID, gemPort, vlanID, classifierInfo, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002540 } else {
2541 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
2542 }
2543 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002544 } else if _, ok := actionInfo[PushVlan]; ok {
2545 log.Info("Adding upstream data rule")
2546 if pcp, ok := classifierInfo[VlanPcp]; ok {
2547 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2548 tp_pb.Direction_UPSTREAM,
2549 pcp.(uint32))
2550 //Adding HSIA upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00002551 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002552 } else {
2553 //Adding HSIA upstream flow to all gemports
2554 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
2555 }
2556 } else if _, ok := actionInfo[PopVlan]; ok {
2557 log.Info("Adding Downstream data rule")
2558 if pcp, ok := classifierInfo[VlanPcp]; ok {
2559 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05002560 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00002561 pcp.(uint32))
2562 //Adding HSIA downstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00002563 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002564 } else {
2565 //Adding HSIA downstream flow to all gemports
2566 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
2567 }
2568 } else {
2569 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
2570 return
2571 }
2572 // Send Techprofile download event to child device in go routine as it takes time
2573 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
2574}
2575
Gamze Abakafee36392019-10-03 11:17:24 +00002576func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
2577 flowIDList := f.flowsUsedByGemPort[gemPK]
2578 if len(flowIDList) > 1 {
2579 return true
2580 }
2581 return false
2582}
2583
Girish Gowdra54934262019-11-13 14:19:55 +05302584func (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 +00002585 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ponIntf, onuID, uniID)
2586 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2587 for _, currentGemPort := range currentGemPorts {
2588 for _, tpGemPort := range tpGemPorts {
2589 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2590 return true, currentGemPort
2591 }
2592 }
2593 }
Girish Gowdra54934262019-11-13 14:19:55 +05302594 if tpInst.InstanceCtrl.Onu == "single-instance" {
2595 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
2596 f.resourceMgr.RemoveTechProfileIDForOnu(ponIntf, uint32(onuID), uint32(uniID), tpID)
2597 f.DeleteTechProfileInstance(ponIntf, uint32(onuID), uint32(uniID), "", tpID)
2598
2599 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
2600 // still be used on other uni ports.
2601 // So, we need to check and make sure that no other gem port is referring to the given TP ID
2602 // on any other uni port.
2603 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(tpID, ponIntf, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302604 log.Debugw("got single instance tp instances", log.Fields{"tpInstances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302605 for i := 0; i < len(tpInstances); i++ {
2606 tpI := tpInstances[i]
2607 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05302608 for _, tpGemPort := range tpGemPorts {
2609 if tpGemPort.GemportID != gemPortID {
2610 log.Debugw("single instance tp is in use by gem", log.Fields{"gemPort": tpGemPort.GemportID})
2611 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05302612 }
2613 }
2614 }
2615 }
Girish Gowdra6b130582019-11-20 16:45:20 +05302616 log.Debug("tech profile is not in use by any gem")
Gamze Abakafee36392019-10-03 11:17:24 +00002617 return false, 0
2618}
2619
salmansiddiqui7ac62132019-08-22 03:58:50 +00002620func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002621 for _, field := range flows.GetOfbFields(flow) {
2622 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002623 classifierInfo[EthType] = field.GetEthType()
2624 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002625 } else if field.Type == flows.ETH_DST {
2626 classifierInfo[EthDst] = field.GetEthDst()
2627 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002628 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002629 classifierInfo[IPProto] = field.GetIpProto()
2630 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002631 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002632 classifierInfo[InPort] = field.GetPort()
2633 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002634 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302635 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00002636 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002637 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002638 classifierInfo[VlanPcp] = field.GetVlanPcp()
2639 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002640 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002641 classifierInfo[UDPDst] = field.GetUdpDst()
2642 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002643 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002644 classifierInfo[UDPSrc] = field.GetUdpSrc()
2645 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002646 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002647 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
2648 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002649 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002650 classifierInfo[Ipv4Src] = field.GetIpv4Src()
2651 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002652 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002653 classifierInfo[Metadata] = field.GetTableMetadata()
2654 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002655 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002656 classifierInfo[TunnelID] = field.GetTunnelId()
2657 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
2658 } else {
2659 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
2660 return
2661 }
2662 }
2663}
2664
2665func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002666 for _, action := range flows.GetActions(flow) {
2667 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002668 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002669 actionInfo[Output] = out.GetPort()
2670 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002671 } else {
2672 log.Error("Invalid output port in action")
2673 return errors.New("invalid output port in action")
2674 }
Scott Baker355d1742019-10-24 10:57:52 -07002675 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002676 actionInfo[PopVlan] = true
2677 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002678 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002679 if out := action.GetPush(); out != nil {
2680 if tpid := out.GetEthertype(); tpid != 0x8100 {
2681 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
2682 } else {
2683 actionInfo[PushVlan] = true
2684 actionInfo[TPID] = tpid
2685 log.Debugw("action-type-push-vlan",
2686 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
2687 }
2688 }
Scott Baker355d1742019-10-24 10:57:52 -07002689 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002690 if out := action.GetSetField(); out != nil {
2691 if field := out.GetField(); field != nil {
2692 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
2693 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
2694 return errors.New("invalid openflow class")
2695 }
2696 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
Esin Karamanccb714b2019-11-29 15:02:06 +00002697 formulateSetFieldActionInfoFromFlow(field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002698 }
2699 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002700 } else if action.Type == flows.GROUP {
2701 formulateGroupActionInfoFromFlow(action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002702 } else {
2703 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
2704 return errors.New("un supported action type")
2705 }
2706 }
2707 return nil
2708}
2709
Esin Karamanccb714b2019-11-29 15:02:06 +00002710func formulateSetFieldActionInfoFromFlow(field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
2711 if ofbField := field.GetOfbField(); ofbField != nil {
2712 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
2713 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2714 actionInfo[VlanVid] = vlan & 0xfff
2715 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
2716 } else {
2717 log.Error("No Invalid vlan id in set vlan-vid action")
2718 }
2719 } else {
2720 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
2721 }
2722 }
2723}
2724
2725func formulateGroupActionInfoFromFlow(action *ofp.OfpAction, actionInfo map[string]interface{}) {
2726 if action.GetGroup() == nil {
2727 log.Warn("No group entry found in the group action")
2728 } else {
2729 actionInfo[GroupID] = action.GetGroup().GroupId
2730 log.Debugw("action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
2731 }
2732}
2733
salmansiddiqui7ac62132019-08-22 03:58:50 +00002734func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002735 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002736 log.Debug("Controller bound trap flows, getting inport from tunnelid")
2737 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2738 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002739 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002740 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07002741 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 +00002742 } else {
2743 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
2744 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
2745 }
2746 }
2747 } else {
2748 log.Debug("Non-Controller flows, getting uniport from tunnelid")
2749 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07002750 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002751 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002752 actionInfo[Output] = uniPort
2753 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 +00002754 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002755 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 +00002756 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
2757 }
2758 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2759 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002760 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002761 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07002762 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
2763 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002764 } else {
2765 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 -07002766 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002767 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
2768 }
2769 }
2770 }
2771 return nil
2772}
Gamze Abakafee36392019-10-03 11:17:24 +00002773
Chaitrashree G S90a17952019-11-14 21:51:21 -05002774func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00002775 /* Metadata 8 bytes:
2776 Most Significant 2 Bytes = Inner VLAN
2777 Next 2 Bytes = Tech Profile ID(TPID)
2778 Least Significant 4 Bytes = Port ID
2779 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
2780 subscriber related flows.
2781 */
2782 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
2783 if metadata == 0 {
Chaitrashree G S90a17952019-11-14 21:51:21 -05002784 log.Error("metadata-is-not-present-in-flow-which-is-mandatory")
2785 return 0, errors.New("metadata-is-not-present-in-flow-which-is-mandatory")
Gamze Abakafee36392019-10-03 11:17:24 +00002786 }
2787 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002788 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00002789}
2790
2791func appendUnique(slice []uint32, item uint32) []uint32 {
2792 for _, sliceElement := range slice {
2793 if sliceElement == item {
2794 return slice
2795 }
2796 }
2797 return append(slice, item)
2798}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302799
2800// getNniIntfID gets nni intf id from the flow classifier/action
2801func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
2802
2803 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
2804 if portType == voltha.Port_PON_OLT {
2805 intfID := IntfIDFromNniPortNum(action[Output].(uint32))
2806 log.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
2807 return intfID, nil
2808 } else if portType == voltha.Port_ETHERNET_NNI {
2809 intfID := IntfIDFromNniPortNum(classifier[InPort].(uint32))
2810 log.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
2811 return intfID, nil
2812 }
2813 return uint32(0), nil
2814}
2815
2816// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
2817func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
2818 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
2819
2820 f.lockCache.Lock()
2821 defer f.lockCache.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05002822 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302823 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05002824 if lookupGemPort == gemPort {
2825 log.Debugw("pktin key/value found in cache , no need to update kv as we are assuming both will be in sync",
2826 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2827 return
2828 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302829 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05002830 f.packetInGemPort[pktInkey] = gemPort
2831
2832 f.resourceMgr.UpdateGemPortForPktIn(pktInkey, gemPort)
2833 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 +05302834 return
2835}
2836
2837// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
2838func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(intfID uint32, onuID uint32, portNum uint32) {
2839
2840 f.lockCache.Lock()
2841 defer f.lockCache.Unlock()
2842 onugem := f.onuGemInfo[intfID]
2843 for idx, onu := range onugem {
2844 if onu.OnuID == onuID {
2845 for _, uni := range onu.UniPorts {
2846 if uni == portNum {
2847 log.Debugw("uni already in cache, no need to update cache and kv store",
2848 log.Fields{"uni": portNum})
2849 return
2850 }
2851 }
2852 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
2853 f.onuGemInfo[intfID] = onugem
2854 }
2855 }
2856 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNum)
2857}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302858
2859func (f *OpenOltFlowMgr) loadFlowIDlistForGem(intf uint32) {
2860 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(intf)
2861 if err != nil {
2862 log.Error("Failed to get flowid list per gem", log.Fields{"intf": intf})
2863 return
2864 }
2865 for gem, FlowIDs := range flowIDsList {
2866 gemPK := gemPortKey{intf, uint32(gem)}
2867 f.flowsUsedByGemPort[gemPK] = FlowIDs
2868 }
2869 return
2870}
Esin Karamanccb714b2019-11-29 15:02:06 +00002871
2872//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
2873//and put them into interfaceToMcastQueueMap.
2874func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap() {
2875 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap()
2876 if err != nil {
2877 log.Error("Failed to get pon interface to multicast queue map")
2878 return
2879 }
2880 for intf, queueInfo := range storedMulticastQueueMap {
2881 q := queueInfoBrief{
2882 gemPortID: queueInfo[0],
2883 servicePriority: queueInfo[1],
2884 }
2885 f.interfaceToMcastQueueMap[intf] = &q
2886 }
2887}
2888
2889//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
2890//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
2891//Returns (nil, false, nil) if the group does not exists in the KV store.
2892func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
2893 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(groupID, cached)
2894 if err != nil {
2895 log.Errorw("Failed to get the flow group from KV store", log.Fields{"groupId": groupID, "err": err})
2896 return nil, false, errors.New("failed to retrieve the flow group")
2897 }
2898 if exists {
2899 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
2900 }
2901 return nil, exists, nil
2902}
2903
2904func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
2905 groupDesc := ofp.OfpGroupDesc{
2906 Type: ofp.OfpGroupType_OFPGT_ALL,
2907 GroupId: groupID,
2908 }
2909 groupEntry := ofp.OfpGroupEntry{
2910 Desc: &groupDesc,
2911 }
2912 var acts []*ofp.OfpAction
2913 for i := 0; i < len(outPorts); i++ {
2914 acts = append(acts, flows.Output(outPorts[i]))
2915 }
2916 bucket := ofp.OfpBucket{
2917 Actions: acts,
2918 }
2919 groupDesc.Buckets = []*ofp.OfpBucket{&bucket}
2920 return &groupEntry
2921}