blob: 892663f51f977e5fcd981157f45af2b0f570938a [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
npujarec5762e2020-01-01 14:08:48 +0530224func NewFlowManager(ctx context.Context, 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++ {
npujarec5762e2020-01-01 14:08:48 +0530244 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530245 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.
npujarec5762e2020-01-01 14:08:48 +0530248 flowMgr.loadFlowIDlistForGem(ctx, 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
npujarec5762e2020-01-01 14:08:48 +0530255 flowMgr.loadInterfaceToMulticastQueueMap(ctx)
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
npujarec5762e2020-01-01 14:08:48 +0530276func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, 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
npujarec5762e2020-01-01 14:08:48 +0530287 f.resourceMgr.UpdateFlowIDsForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400288}
289
npujarec5762e2020-01-01 14:08:48 +0530290func (f *OpenOltFlowMgr) divideAndAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000291 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) {
npujarec5762e2020-01-01 14:08:48 +0530312 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530313 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 */
npujarec5762e2020-01-01 14:08:48 +0530328 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530329 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
npujarec5762e2020-01-01 14:08:48 +0530338func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, 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
npujarec5762e2020-01-01 14:08:48 +0530355 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, 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
npujarec5762e2020-01-01 14:08:48 +0530412 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000413 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 */
npujarec5762e2020-01-01 14:08:48 +0530420 if err := f.resourceMgr.UpdateMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000421 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
npujarec5762e2020-01-01 14:08:48 +0530429func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000430
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})
npujarec5762e2020-01-01 14:08:48 +0530439 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000440 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})
npujarec5762e2020-01-01 14:08:48 +0530450 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000451 &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
npujarec5762e2020-01-01 14:08:48 +0530471 f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID,
Esin Karamanccb714b2019-11-29 15:02:06 +0000472 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
npujarec5762e2020-01-01 14:08:48 +0530481func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, 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
npujarec5762e2020-01-01 14:08:48 +0530501 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, 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
npujarec5762e2020-01-01 14:08:48 +0530527 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
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")
npujarec5762e2020-01-01 14:08:48 +0530535 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &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 */
npujarec5762e2020-01-01 14:08:48 +0530548 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, 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
npujarec5762e2020-01-01 14:08:48 +0530558func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) (uint32, []uint32, *tp.TechProfile) {
Gamze Abakafee36392019-10-03 11:17:24 +0000559 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
npujarec5762e2020-01-01 14:08:48 +0530565 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
566 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, 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
npujarec5762e2020-01-01 14:08:48 +0530573 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, 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})
npujarec5762e2020-01-01 14:08:48 +0530576 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000577 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 }
npujarec5762e2020-01-01 14:08:48 +0530582 f.resourceMgr.UpdateTechProfileIDForOnu(ctx, 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}
npujarec5762e2020-01-01 14:08:48 +0530590 if err := f.CreateSchedulerQueues(ctx, 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}
npujarec5762e2020-01-01 14:08:48 +0530598 if err := f.CreateSchedulerQueues(ctx, 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
npujarec5762e2020-01-01 14:08:48 +0530620 f.storeTcontsGEMPortsIntoKVStore(ctx, 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
npujarec5762e2020-01-01 14:08:48 +0530624func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, 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 */
npujarec5762e2020-01-01 14:08:48 +0530629 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530630 log.Error("Errow while uploading allocID to KV store")
631 }
npujarec5762e2020-01-01 14:08:48 +0530632 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530633 log.Error("Errow while uploading GEMports to KV store")
634 }
npujarec5762e2020-01-01 14:08:48 +0530635 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, 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 {
npujarec5762e2020-01-01 14:08:48 +0530640 f.addGemPortToOnuInfoMap(ctx, 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
npujarec5762e2020-01-01 14:08:48 +0530664func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, 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})
npujarec5762e2020-01-01 14:08:48 +0530670 f.addHSIAFlow(ctx, 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
npujarec5762e2020-01-01 14:08:48 +0530675func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, 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
npujarec5762e2020-01-01 14:08:48 +0530705 f.addHSIAFlow(ctx, 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
npujarec5762e2020-01-01 14:08:48 +0530709func (f *OpenOltFlowMgr) addHSIAFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +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)
npujarec5762e2020-01-01 14:08:48 +0530729 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Gowdra3d633032019-12-10 16:37:05 +0530730 log.Debug("Flow-exists--not-re-adding")
731 return
732 }
npujarec5762e2020-01-01 14:08:48 +0530733 flowID, err := f.resourceMgr.GetFlowID(ctx, 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}
npujarec5762e2020-01-01 14:08:48 +0530768 if ok := f.addFlowToDevice(ctx, logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530769 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
npujarec5762e2020-01-01 14:08:48 +0530770 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
771 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
Manikkaraj k884c1242019-04-11 16:26:42 +0530772 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
npujarec5762e2020-01-01 14:08:48 +0530781func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32) {
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)
npujarec5762e2020-01-01 14:08:48 +0530805 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Gowdra3d633032019-12-10 16:37:05 +0530806 log.Debug("Flow-exists--not-re-adding")
807 return
808 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530809
npujarec5762e2020-01-01 14:08:48 +0530810 flowID, err = f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, DhcpFlow, 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +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
npujarec5762e2020-01-01 14:08:48 +0530843 if ok := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530844 log.Debug("DHCP UL flow added to device successfully")
npujarec5762e2020-01-01 14:08:48 +0530845 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
846 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530847 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
npujarec5762e2020-01-01 14:08:48 +0530859func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Esin Karamanae41e2b2019-12-17 18:13:13 +0000860 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32) {
npujarec5762e2020-01-01 14:08:48 +0530861 f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow)
Esin Karamanae41e2b2019-12-17 18:13:13 +0000862}
863
864//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +0530865func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Esin Karamanae41e2b2019-12-17 18:13:13 +0000866 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)
npujarec5762e2020-01-01 14:08:48 +0530888 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Esin Karamanae41e2b2019-12-17 18:13:13 +0000889 log.Debug("Flow-exists--not-re-adding")
890 return
891 }
892
npujarec5762e2020-01-01 14:08:48 +0530893 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, flowType, 0, 0 /*classifier[VLAN_PCP].(uint32)*/)
Esin Karamanae41e2b2019-12-17 18:13:13 +0000894
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
npujarec5762e2020-01-01 14:08:48 +0530926 if ok := f.addFlowToDevice(ctx, logicalFlow, &flow); ok {
Esin Karamanae41e2b2019-12-17 18:13:13 +0000927 log.Debugf("%s UL flow added to device successfully", flowType)
928
npujarec5762e2020-01-01 14:08:48 +0530929 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
930 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
Esin Karamanae41e2b2019-12-17 18:13:13 +0000931 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
npujarec5762e2020-01-01 14:08:48 +0530943func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, 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)
npujarec5762e2020-01-01 14:08:48 +0530959 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Gowdra3d633032019-12-10 16:37:05 +0530960 log.Debug("Flow-exists--not-re-adding")
961 return
962 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530963 //Add Uplink EAPOL Flow
npujarec5762e2020-01-01 14:08:48 +0530964 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, 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}
npujarec5762e2020-01-01 14:08:48 +05301002 if ok := f.addFlowToDevice(ctx, 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"
npujarec5762e2020-01-01 14:08:48 +05301005 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1006 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
manikkaraj kbf256be2019-03-25 00:13:48 +05301007 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
npujarec5762e2020-01-01 14:08:48 +05301088func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1089 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, 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 {
npujarec5762e2020-01-01 14:08:48 +05301092 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +00001093 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
npujarec5762e2020-01-01 14:08:48 +05301102func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001103 if uniPortName == "" {
1104 uniPortName = fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1105 }
npujarec5762e2020-01-01 14:08:48 +05301106 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001107 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
npujarec5762e2020-01-01 14:08:48 +05301140func (f *OpenOltFlowMgr) getUpdatedFlowInfo(ctx context.Context, flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32, logicalFlowID uint64) *[]rsrcMgr.FlowInfo {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301141 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
npujarec5762e2020-01-01 14:08:48 +05301152 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, 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
npujarec5762e2020-01-01 14:08:48 +05301187func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(ctx context.Context, 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})
npujarec5762e2020-01-01 14:08:48 +05301189 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, 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
npujarec5762e2020-01-01 14:08:48 +05301197func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, 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})
npujarec5762e2020-01-01 14:08:48 +05301221 f.resourceMgr.FreeFlowID(ctx, 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.
npujarec5762e2020-01-01 14:08:48 +05301226 f.registerFlow(ctx, logicalFlow, deviceFlow)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301227 }
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
npujarec5762e2020-01-01 14:08:48 +05301269func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) {
Humera Kouser94d7a842019-08-25 19:04:32 -04001270
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))
npujarec5762e2020-01-01 14:08:48 +05301296 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, 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 }
npujarec5762e2020-01-01 14:08:48 +05301300 flowID, err := f.resourceMgr.GetFlowID(ctx, 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}
npujarec5762e2020-01-01 14:08:48 +05301331 if ok := f.addFlowToDevice(ctx, flow, &downstreamflow); ok {
Humera Kouser94d7a842019-08-25 19:04:32 -04001332 log.Debug("LLDP trap on NNI flow added to device successfully")
npujarec5762e2020-01-01 14:08:48 +05301333 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1334 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
Humera Kouser94d7a842019-08-25 19:04:32 -04001335 int32(onuID),
1336 int32(uniID),
1337 flowID, flowsToKVStore); err != nil {
1338 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1339 }
1340 }
1341 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301342}
1343
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301344func getUniPortPath(intfID uint32, onuID int32, uniID int32) string {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001345 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1346}
1347
1348//getOnuChildDevice to fetch onu
1349func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1350 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1351 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1352 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301353 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001354 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301355 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301356 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301357 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1358 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301359}
1360
1361func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001362 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301363 return nil
1364}
1365
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001366func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1367 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301368}
1369
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001370func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001371 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001372 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001373 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001374 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001375}
1376
Girish Gowdra6b130582019-11-20 16:45:20 +05301377func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1378 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1379 if err != nil {
1380 log.Errorw("error fetching child device from core", log.Fields{"onuId": onuID})
1381 return err
1382 }
1383
1384 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
1385 log.Debugw("sending gem port delete to openonu adapter", log.Fields{"msg": *delGemPortMsg})
1386 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1387 delGemPortMsg,
1388 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
1389 f.deviceHandler.deviceType,
1390 onuDevice.Type,
1391 onuDevice.Id,
1392 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
1393 log.Errorw("failure sending del gem port to onu adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1394 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1395 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1396 return sendErr
1397 }
1398 log.Debugw("success sending del gem port to onu adapter", log.Fields{"msg": delGemPortMsg})
1399 return nil
1400}
1401
1402func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1403 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1404 if err != nil {
1405 log.Errorw("error fetching child device from core", log.Fields{"onuId": onuID})
1406 return err
1407 }
1408
1409 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
1410 log.Debugw("sending tcont delete to openonu adapter", log.Fields{"msg": *delTcontMsg})
1411 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1412 delTcontMsg,
1413 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
1414 f.deviceHandler.deviceType,
1415 onuDevice.Type,
1416 onuDevice.Id,
1417 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
1418 log.Errorw("failure sending del tcont to onu adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1419 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1420 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1421 return sendErr
1422 }
1423 log.Debugw("success sending del tcont to onu adapter", log.Fields{"msg": delTcontMsg})
1424 return nil
1425}
1426
Girish Gowdra3d633032019-12-10 16:37:05 +05301427func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1428 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1429 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1430 if val.(int) > 0 {
1431 pnFlDels := val.(int) - 1
1432 if pnFlDels > 0 {
1433 log.Debugw("flow delete succeeded, more pending",
1434 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1435 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1436 } else {
1437 log.Debugw("all pending flow deletes handled, removing entry from map",
1438 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1439 f.pendingFlowDelete.Delete(pnFlDelKey)
1440 }
1441 }
1442 } else {
1443 log.Debugw("no pending delete flows found",
1444 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1445
1446 }
1447
1448}
1449
Girish Gowdrac3037402020-01-22 20:29:53 +05301450// Once the gemport is released for a given onu, it also has to be cleared from local cache
1451// which was used for deriving the gemport->logicalPortNo during packet-in.
1452// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1453// is conveyed to ONOS during packet-in OF message.
1454func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(intfID uint32, onuID uint32, gemPortID uint32) {
1455 f.lockCache.Lock()
1456 defer f.lockCache.Unlock()
1457 onugem := f.onuGemInfo[intfID]
1458 for _, onu := range onugem {
1459 if onu.OnuID == onuID {
1460 for i, gem := range onu.GemPorts {
1461 // If the gemport is found, delete it from local cache.
1462 if gem == gemPortID {
1463 onu.GemPorts = append(onu.GemPorts[:i], onu.GemPorts[i+1:]...)
1464 log.Debugw("removed gemport from local cache",
1465 log.Fields{"intfID": intfID, "onuID": onuID, "gemPortID": gemPortID})
1466 break
1467 }
1468 }
1469 break
1470 }
1471 }
1472}
1473
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301474//clearResources clears pon resources in kv store and the device
npujarec5762e2020-01-01 14:08:48 +05301475func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301476 gemPortID int32, flowID uint32, flowDirection string,
1477 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001478
Chaitrashree G S90a17952019-11-14 21:51:21 -05001479 tpID, err := getTpIDFromFlow(flow)
1480 if err != nil {
1481 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID})
1482 return err
1483 }
Gamze Abakafee36392019-10-03 11:17:24 +00001484
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001485 if len(updatedFlows) >= 0 {
1486 // There are still flows referencing the same flow_id.
1487 // So the flow should not be freed yet.
1488 // For ex: Case of HSIA where same flow is shared
1489 // between DS and US.
npujarec5762e2020-01-01 14:08:48 +05301490 f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001491 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05301492 // Do this for subscriber flows only (not trap from NNI flows)
1493 if onuID != -1 && uniID != -1 {
1494 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1495 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
1496 log.Debugw("creating entry for pending flow delete",
1497 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1498 f.pendingFlowDelete.Store(pnFlDelKey, 1)
1499 } else {
1500 pnFlDels := val.(int) + 1
1501 log.Debugw("updating flow delete entry",
1502 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1503 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1504 }
1505
1506 defer f.deletePendingFlows(Intf, onuID, uniID)
1507 }
1508
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301509 log.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
npujarec5762e2020-01-01 14:08:48 +05301510 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001511
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301512 uni := getUniPortPath(Intf, onuID, uniID)
1513 tpPath := f.getTPpath(Intf, uni, tpID)
Gamze Abakafee36392019-10-03 11:17:24 +00001514 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
npujarec5762e2020-01-01 14:08:48 +05301515 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Gamze Abakafee36392019-10-03 11:17:24 +00001516 if err != nil { // This should not happen, something wrong in KV backend transaction
1517 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301518 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001519 }
1520 if techprofileInst == nil {
1521 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301522 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001523 }
1524
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301525 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001526 if f.isGemPortUsedByAnotherFlow(gemPK) {
1527 flowIDs := f.flowsUsedByGemPort[gemPK]
1528 for i, flowIDinMap := range flowIDs {
1529 if flowIDinMap == flowID {
1530 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301531 // everytime flowsUsedByGemPort cache is updated the same should be updated
1532 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001533 f.flowsUsedByGemPort[gemPK] = flowIDs
npujarec5762e2020-01-01 14:08:48 +05301534 f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00001535 break
1536 }
1537 }
1538 log.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301539 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001540 }
Gamze Abakafee36392019-10-03 11:17:24 +00001541 log.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301542 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001543 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1544 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
npujarec5762e2020-01-01 14:08:48 +05301545 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Girish Gowdrac3037402020-01-22 20:29:53 +05301546 f.deleteGemPortFromLocalCache(Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001547 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301548 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1549 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001550 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05301551 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1552 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001553 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05301554 // Delete the gem port on the ONU.
1555 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1556 log.Errorw("error processing delete gem-port towards onu",
1557 log.Fields{"err": err, "pon": Intf, "onuID": onuID, "uniID": uniID, "gemPortId": gemPortID})
1558 }
Gamze Abakafee36392019-10-03 11:17:24 +00001559
npujarec5762e2020-01-01 14:08:48 +05301560 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001561 if !ok {
npujarec5762e2020-01-01 14:08:48 +05301562 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
1563 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1564 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1565 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
1566 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301567 // Delete the TCONT on the ONU.
1568 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
1569 log.Errorw("error processing delete tcont towards onu",
1570 log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID, "allocId": techprofileInst.UsScheduler.AllocID})
1571 }
Gamze Abakafee36392019-10-03 11:17:24 +00001572 }
1573 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001574 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301575 return nil
1576}
1577
npujarec5762e2020-01-01 14:08:48 +05301578func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301579
1580 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
Esin Karamanccb714b2019-11-29 15:02:06 +00001581
1582 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05301583 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001584 return
1585 }
1586
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301587 var updatedFlows []rsrcMgr.FlowInfo
1588 var flowID uint32
1589 var onuID, uniID int32
1590 classifierInfo := make(map[string]interface{})
1591
1592 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1593 if err != nil {
1594 log.Error(err)
1595 return
1596 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301597
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301598 onuID = int32(onu)
1599 uniID = int32(uni)
1600
1601 for _, field := range flows.GetOfbFields(flow) {
1602 if field.Type == flows.IP_PROTO {
1603 classifierInfo[IPProto] = field.GetIpProto()
1604 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1605 }
1606 }
1607 log.Debugw("Extracted access info from flow to be deleted",
1608 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1609
1610 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1611 onuID = -1
1612 uniID = -1
1613 log.Debug("Trap on nni flow set oni, uni to -1")
1614 Intf = IntfIDFromNniPortNum(inPort)
1615 }
npujarec5762e2020-01-01 14:08:48 +05301616 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301617 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05301618 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301619 if flowInfo == nil {
1620 log.Debugw("No FlowInfo found found in KV store",
1621 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1622 return
1623 }
1624 updatedFlows = nil
1625 for _, flow := range *flowInfo {
1626 updatedFlows = append(updatedFlows, flow)
1627 }
1628
1629 for i, storedFlow := range updatedFlows {
1630 if flow.Id == storedFlow.LogicalFlowID {
1631 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1632 log.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
1633 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1634 log.Debug("Flow removed from device successfully")
1635 //Remove the Flow from FlowInfo
1636 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05301637 err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301638 flowID, flowDirection, portNum, updatedFlows)
1639 if err != nil {
1640 log.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
1641 return
1642 }
1643 } else {
1644 log.Error("Failed to remove flow from device")
1645 return
1646 }
1647 }
1648 }
1649 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001650}
1651
Esin Karamanccb714b2019-11-29 15:02:06 +00001652//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
1653// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05301654func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00001655 classifierInfo := make(map[string]interface{})
1656 formulateClassifierInfoFromFlow(classifierInfo, flow)
npujarec5762e2020-01-01 14:08:48 +05301657 inPort, err := f.getInPortOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00001658
1659 if err != nil {
1660 log.Warnw("No inPort found. Cannot release resources of the multicast flow.", log.Fields{"flowId:": flow.Id})
1661 return
1662 }
1663
1664 networkInterfaceID := IntfIDFromNniPortNum(inPort)
1665 var onuID = int32(NoneOnuID)
1666 var uniID = int32(NoneUniID)
1667 var flowID uint32
1668 var updatedFlows []rsrcMgr.FlowInfo
1669
npujarec5762e2020-01-01 14:08:48 +05301670 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001671
1672 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05301673 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001674 if flowInfo == nil {
1675 log.Debugw("No multicast FlowInfo found in the KV store",
1676 log.Fields{"Intf": networkInterfaceID, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1677 continue
1678 }
1679 updatedFlows = nil
1680 for _, flow := range *flowInfo {
1681 updatedFlows = append(updatedFlows, flow)
1682 }
1683 for i, storedFlow := range updatedFlows {
1684 if flow.Id == storedFlow.LogicalFlowID {
1685 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1686 log.Debugw("Multicast flow to be deleted", log.Fields{"flow": storedFlow})
1687 //remove from device
1688 if ok := f.removeFlowFromDevice(&removeFlowMessage); !ok {
1689 log.Errorw("Failed to remove multicast flow from device", log.Fields{"flowId": flow.Id})
1690 return
1691 }
1692 log.Debugw("Multicast flow removed from device successfully", log.Fields{"flowId": flow.Id})
1693 //Remove the Flow from FlowInfo
1694 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05301695 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Esin Karamanccb714b2019-11-29 15:02:06 +00001696 log.Error("Failed to delete multicast flow from the KV store", log.Fields{"flow": storedFlow, "err": err})
1697 return
1698 }
1699 //release flow id
1700 log.Debugw("Releasing multicast flow id", log.Fields{"flowId": flowID, "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05301701 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001702 }
1703 }
1704 }
1705}
1706
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001707//RemoveFlow removes the flow from the device
npujarec5762e2020-01-01 14:08:48 +05301708func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001709 log.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301710 var direction string
1711 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001712
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301713 for _, action := range flows.GetActions(flow) {
1714 if action.Type == flows.OUTPUT {
1715 if out := action.GetOutput(); out != nil {
1716 actionInfo[Output] = out.GetPort()
1717 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
1718 } else {
1719 log.Error("Invalid output port in action")
1720 return
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001721 }
1722 }
1723 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001724
1725 if flows.HasGroup(flow) {
1726 direction = Multicast
1727 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301728 direction = Upstream
1729 } else {
1730 direction = Downstream
1731 }
npujarec5762e2020-01-01 14:08:48 +05301732 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301733
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001734 return
1735}
1736
Girish Gowdra3d633032019-12-10 16:37:05 +05301737func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
1738 uniID uint32, ch chan bool) {
1739 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1740 for {
1741 select {
1742 case <-time.After(20 * time.Millisecond):
1743 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
1744 log.Debug("pending flow deletes completed")
1745 ch <- true
1746 return
1747 }
1748 case <-ctx.Done():
1749 log.Error("flow delete wait handler routine canceled")
1750 return
1751 }
1752 }
1753}
1754
Esin Karamanae41e2b2019-12-17 18:13:13 +00001755//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
1756func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
1757 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
1758 if ethType, ok := classifierInfo[EthType]; ok {
1759 if ethType.(uint32) == IPv4EthType {
1760 if ipProto, ok := classifierInfo[IPProto]; ok {
1761 if ipProto.(uint32) == IgmpProto {
1762 return true
1763 }
1764 }
1765 }
1766 }
1767 }
1768 return false
1769}
1770
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001771// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301772// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301773func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001774 classifierInfo := make(map[string]interface{})
1775 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001776 var UsMeterID uint32
1777 var DsMeterID uint32
1778
1779 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001780 formulateClassifierInfoFromFlow(classifierInfo, flow)
1781
1782 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1783 if err != nil {
1784 // Error logging is already done in the called function
1785 // So just return in case of error
1786 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301787 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001788
Esin Karamanccb714b2019-11-29 15:02:06 +00001789 if flows.HasGroup(flow) {
1790 // handle multicast flow
npujarec5762e2020-01-01 14:08:48 +05301791 f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001792 return
1793 }
1794
manikkaraj k17652a72019-05-06 09:06:36 -04001795 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001796 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1797 if err != nil {
1798 // error if any, already logged in the called function
1799 return
manikkaraj k17652a72019-05-06 09:06:36 -04001800 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001801
David K. Bainbridge82efc492019-09-04 09:57:11 -07001802 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1803 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001804
Humera Kouser94d7a842019-08-25 19:04:32 -04001805 if ethType, ok := classifierInfo[EthType]; ok {
1806 if ethType.(uint32) == LldpEthType {
1807 log.Info("Adding LLDP flow")
npujarec5762e2020-01-01 14:08:48 +05301808 f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04001809 return
1810 }
1811 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001812 if ipProto, ok := classifierInfo[IPProto]; ok {
1813 if ipProto.(uint32) == IPProtoDhcp {
1814 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301815 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001816 log.Debug("trap-dhcp-from-nni-flow")
npujarec5762e2020-01-01 14:08:48 +05301817 f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001818 return
1819 }
1820 }
1821 }
1822 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001823 if isIgmpTrapDownstreamFlow(classifierInfo) {
1824 log.Debug("trap-igmp-from-nni-flow")
npujarec5762e2020-01-01 14:08:48 +05301825 f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001826 return
1827 }
A R Karthick1f85b802019-10-11 05:06:05 +00001828
1829 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
npujarec5762e2020-01-01 14:08:48 +05301830 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001831
Chaitrashree G S90a17952019-11-14 21:51:21 -05001832 TpID, err := getTpIDFromFlow(flow)
1833 if err != nil {
1834 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1835 return
1836 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001837 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001838 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001839 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001840 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1841 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001842 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001843 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1844
1845 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301846
1847 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1848 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
1849 log.Debugw("no pending flows found, going ahead with flow install", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
npujarec5762e2020-01-01 14:08:48 +05301850 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05301851 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05301852 pendingFlowDelComplete := make(chan bool)
1853 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
1854 select {
1855 case <-pendingFlowDelComplete:
1856 log.Debugw("all pending flow deletes completed", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
npujarec5762e2020-01-01 14:08:48 +05301857 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05301858
1859 case <-time.After(10 * time.Second):
1860 log.Errorw("pending flow deletes not completed after timeout", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1861 }
1862 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001863}
1864
Esin Karamanccb714b2019-11-29 15:02:06 +00001865// handleFlowWithGroup adds multicast flow to the device.
npujarec5762e2020-01-01 14:08:48 +05301866func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00001867 classifierInfo[PacketTagType] = DoubleTag
1868 log.Debugw("add-multicast-flow", log.Fields{"classifierInfo": classifierInfo, "actionInfo": actionInfo})
1869
npujarec5762e2020-01-01 14:08:48 +05301870 inPort, err := f.getInPortOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00001871 if err != nil {
1872 log.Warnw("No inPort found. Ignoring multicast flow.", log.Fields{"flowId:": flow.Id})
1873 return
1874 }
1875 //replace ipDst with ethDst
1876 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
1877 flows.IsMulticastIp(ipv4Dst.(uint32)) {
1878 // replace ipv4_dst classifier with eth_dst
1879 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
1880 delete(classifierInfo, Ipv4Dst)
1881 delete(classifierInfo, EthType)
1882 classifierInfo[EthDst] = multicastMac
1883 log.Debugw("multicast-ip-to-mac-conversion-success", log.Fields{"ip:": ipv4Dst.(uint32), "mac:": multicastMac})
1884 }
1885
1886 var onuID = NoneOnuID
1887 var uniID = NoneUniID
1888 var gemPortID = NoneGemPortID
1889
1890 networkInterfaceID := IntfIDFromNniPortNum(inPort)
1891
1892 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301893 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Esin Karamanccb714b2019-11-29 15:02:06 +00001894 log.Debugw("multicast-flow-exists--not-re-adding", log.Fields{"classifierInfo": classifierInfo})
1895 return
1896 }
npujarec5762e2020-01-01 14:08:48 +05301897 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00001898 if err != nil {
1899 log.Errorw("Flow id unavailable for multicast flow", log.Fields{"error": err})
1900 return
1901 }
1902 var classifierProto *openoltpb2.Classifier
1903 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1904 log.Error("Error in making classifier protobuf for multicast flow")
1905 return
1906 }
1907 groupID := actionInfo[GroupID].(uint32)
1908 multicastFlow := openoltpb2.Flow{
1909 FlowId: flowID,
1910 FlowType: Multicast,
1911 NetworkIntfId: int32(networkInterfaceID),
1912 GroupId: groupID,
1913 Classifier: classifierProto,
1914 Priority: int32(flow.Priority),
1915 Cookie: flow.Cookie}
1916
npujarec5762e2020-01-01 14:08:48 +05301917 if ok := f.addFlowToDevice(ctx, flow, &multicastFlow); ok {
Esin Karamanccb714b2019-11-29 15:02:06 +00001918 log.Debug("multicast flow added to device successfully")
1919 //get cached group
npujarec5762e2020-01-01 14:08:48 +05301920 group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true)
Esin Karamanccb714b2019-11-29 15:02:06 +00001921 if err == nil {
1922 //calling groupAdd to set group members after multicast flow creation
npujarec5762e2020-01-01 14:08:48 +05301923 if f.ModifyGroup(ctx, group) {
Esin Karamanccb714b2019-11-29 15:02:06 +00001924 //cached group can be removed now
npujarec5762e2020-01-01 14:08:48 +05301925 f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true)
Esin Karamanccb714b2019-11-29 15:02:06 +00001926 }
1927 }
1928
npujarec5762e2020-01-01 14:08:48 +05301929 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
1930 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
Esin Karamanccb714b2019-11-29 15:02:06 +00001931 int32(onuID),
1932 int32(uniID),
1933 flowID, flowsToKVStore); err != nil {
1934 log.Errorw("Error uploading multicast flow into KV store", log.Fields{"flow": multicastFlow, "error": err})
1935 }
1936 }
1937 return
1938}
1939
1940//getInPortOfMulticastFlow return inPort criterion if exists; returns NNI interface of the device otherwise
npujarec5762e2020-01-01 14:08:48 +05301941func (f *OpenOltFlowMgr) getInPortOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
Esin Karamanccb714b2019-11-29 15:02:06 +00001942 if _, ok := classifierInfo[InPort]; ok {
1943 return classifierInfo[InPort].(uint32), nil
1944 }
1945 // find first NNI port of the device
npujarec5762e2020-01-01 14:08:48 +05301946 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00001947 if e == nil && len(nniPorts) > 0 {
1948 return nniPorts[0], nil
1949 }
1950 return 0, errors.New("cannot find NNI port of device")
1951}
1952
1953// AddGroup add or update the group
npujarec5762e2020-01-01 14:08:48 +05301954func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) {
Esin Karamanccb714b2019-11-29 15:02:06 +00001955 log.Infow("add-group", log.Fields{"group": group})
1956 if group == nil {
1957 log.Warn("skipping nil group")
1958 return
1959 }
1960
1961 groupToOlt := openoltpb2.Group{
1962 GroupId: group.Desc.GroupId,
1963 Command: openoltpb2.Group_SET_MEMBERS,
1964 Action: f.buildGroupAction(),
1965 }
1966
1967 log.Debugw("Sending group to device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05301968 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00001969 if err != nil {
1970 log.Errorw("add-group operation failed", log.Fields{"err": err, "groupToOlt": groupToOlt})
1971 return
1972 }
1973 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05301974 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Esin Karamanccb714b2019-11-29 15:02:06 +00001975 log.Errorw("Group cannot be stored in KV store", log.Fields{"groupId": group.Desc.GroupId, "err": err})
1976 } else {
1977 log.Debugw("add-group operation performed on the device successfully ", log.Fields{"groupToOlt": groupToOlt})
1978 }
1979}
1980
1981//buildGroupAction creates and returns a group action
1982func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
1983 var actionCmd openoltpb2.ActionCmd
1984 var action openoltpb2.Action
1985 action.Cmd = &actionCmd
1986 //pop outer vlan
1987 action.Cmd.RemoveOuterTag = true
1988 return &action
1989}
1990
1991// ModifyGroup updates the group
npujarec5762e2020-01-01 14:08:48 +05301992func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) bool {
Esin Karamanccb714b2019-11-29 15:02:06 +00001993 log.Infow("modify-group", log.Fields{"group": group})
1994 if group == nil || group.Desc == nil {
1995 log.Warn("cannot modify group; group is nil")
1996 return false
1997 }
1998
1999 new := f.buildGroup(group.Desc.GroupId, group.Desc.Buckets)
2000 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302001 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002002
2003 if err != nil {
2004 log.Errorw("Failed to retrieve the group from the store. Cannot modify group.",
2005 log.Fields{"groupId": group.Desc.GroupId, "err": err})
2006 return false
2007 }
2008
2009 var current *openoltpb2.Group
2010 if groupExists {
2011 // group already exists
2012 current = f.buildGroup(group.Desc.GroupId, val.Desc.GetBuckets())
2013 log.Debugw("modify-group: group exists.", log.Fields{"current": val, "new": group})
2014 } else {
2015 current = f.buildGroup(group.Desc.GroupId, nil)
2016 }
2017
2018 log.Debugw("modify-group: comparing current and new.", log.Fields{"current": current, "new": new})
2019 // check if the buckets are identical
2020 bucketsIdentical := f.bucketsIdentical(current, new)
2021
2022 isSuccess := true
2023 if !bucketsIdentical {
2024 groupToOlt := openoltpb2.Group{
2025 GroupId: group.Desc.GroupId,
2026 Command: openoltpb2.Group_SET_MEMBERS,
2027 Members: new.Members,
2028 Action: f.buildGroupAction(),
2029 }
2030
2031 if err := f.callGroupAdd(&groupToOlt); err != nil {
2032 log.Warnw("One of the group add/remove operations has failed. Cannot save group modifications",
2033 log.Fields{"group": group})
2034 isSuccess = false
2035 }
2036 }
2037
2038 if isSuccess {
npujarec5762e2020-01-01 14:08:48 +05302039 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Esin Karamanccb714b2019-11-29 15:02:06 +00002040 log.Errorw("Failed to save the group into kv store", log.Fields{"groupId": group.Desc.GroupId})
2041 }
2042 log.Debugw("modify-group was success. Storing the group", log.Fields{"group": group, "existingGroup": current})
2043 }
2044 return isSuccess
2045}
2046
2047//bucketsIdentical returns true if groups are identical; false otherwise
2048func (f *OpenOltFlowMgr) bucketsIdentical(current *openoltpb2.Group, new *openoltpb2.Group) bool {
2049 if current.GroupId == new.GroupId &&
2050 len(new.Members) == len(current.Members) {
2051 diff := f.findDiff(current, new)
2052 if diff == nil || len(diff) < 1 {
2053 log.Infow("modify-group: current and new buckets are the same. Won't send SET_MEMBERS again.",
2054 log.Fields{"groupId:": current.GroupId})
2055 return true
2056 }
2057 }
2058 return false
2059}
2060
2061//findDiff compares group members and finds members which only exists in groups2
2062func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2063 var members []*openoltpb2.GroupMember
2064 for _, bucket := range group2.Members {
2065 if !f.contains(group1.Members, bucket) {
2066 // bucket does not exist and must be added
2067 members = append(members, bucket)
2068 }
2069 }
2070 return members
2071}
2072
2073//contains returns true if the members list contains the given member; false otherwise
2074func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2075 for _, groupMember := range members {
2076 if groupMember.InterfaceId == member.InterfaceId {
2077 return true
2078 }
2079 }
2080 return false
2081}
2082
2083//callGroupAdd call GroupAdd operation of openolt proto
2084func (f *OpenOltFlowMgr) callGroupAdd(group *openoltpb2.Group) error {
2085 log.Debugw("Sending group to device", log.Fields{"groupToOlt": group, "command": group.Command})
2086 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2087 if err != nil {
2088 log.Errorw("group operation failed", log.Fields{"err": err, "groupToOlt": group})
2089 }
2090 return err
2091}
2092
2093//buildGroup build openoltpb2.Group from given group id and bucket list
2094func (f *OpenOltFlowMgr) buildGroup(groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
2095 group := openoltpb2.Group{
2096 GroupId: groupID}
2097 // create members of the group
2098 if buckets != nil {
2099 for _, ofBucket := range buckets {
2100 member := f.buildMember(ofBucket)
2101 if member != nil && !f.contains(group.Members, member) {
2102 group.Members = append(group.Members, member)
2103 }
2104 }
2105 }
2106 return &group
2107}
2108
2109//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
2110func (f *OpenOltFlowMgr) buildMember(ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
2111 var outPort uint32
2112 outPortFound := false
2113 for _, ofAction := range ofBucket.Actions {
2114 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2115 outPort = ofAction.GetOutput().Port
2116 outPortFound = true
2117 }
2118 }
2119
2120 if !outPortFound {
2121 log.Debugw("bucket skipped since no out port found in it",
2122 log.Fields{"ofBucket": ofBucket})
2123 return nil
2124 }
2125 interfaceID := IntfIDFromUniPortNum(outPort)
2126 log.Debugw("got associated interface id of the port", log.Fields{"portNumber:": outPort, "interfaceId:": interfaceID})
2127 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2128 member := openoltpb2.GroupMember{
2129 InterfaceId: interfaceID,
2130 InterfaceType: openoltpb2.GroupMember_PON,
2131 GemPortId: groupInfo.gemPortID,
2132 Priority: groupInfo.servicePriority,
2133 }
2134 //add member to the group
2135 return &member
2136 }
2137 log.Warnf("bucket skipped since interface-2-gem mapping cannot be found",
2138 log.Fields{"ofBucket": ofBucket})
2139 return nil
2140}
2141
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002142//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04002143func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002144
2145 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302146 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002147 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05302148 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302149 }
Manikkaraj k884c1242019-04-11 16:26:42 +05302150 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04002151
Manikkaraj kb1d51442019-07-23 10:41:02 -04002152 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002153 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04002154 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
2155 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2156 tpDownloadMsg,
2157 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
2158 f.deviceHandler.deviceType,
2159 onuDevice.Type,
2160 onuDevice.Id,
2161 onuDevice.ProxyAddress.DeviceId, "")
2162 if sendErr != nil {
2163 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
2164 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
2165 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
2166 return sendErr
2167 }
2168 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302169 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302170}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002171
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302172//UpdateOnuInfo function adds onu info to cache and kvstore
npujarec5762e2020-01-01 14:08:48 +05302173func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302174
2175 f.lockCache.Lock()
2176 defer f.lockCache.Unlock()
2177 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2178 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
npujarec5762e2020-01-01 14:08:48 +05302179 if err := f.resourceMgr.AddOnuInfo(ctx, intfID, onu); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302180 log.Errorw("failed to add onu info", log.Fields{"onu": onu})
2181 return
2182 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002183 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
2184}
2185
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302186//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302187func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302188 f.lockCache.Lock()
2189 defer f.lockCache.Unlock()
2190 onugem := f.onuGemInfo[intfID]
2191 // update the gem to the local cache as well as to kv strore
2192 for idx, onu := range onugem {
2193 if onu.OnuID == onuID {
2194 // check if gem already exists , else update the cache and kvstore
2195 for _, gem := range onu.GemPorts {
2196 if gem == gemPort {
2197 log.Debugw("Gem already in cache, no need to update cache and kv store",
2198 log.Fields{"gem": gemPort})
2199 return
2200 }</