blob: d14194ef2cdb187330fefaa354b15dee0ca8579c [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
22 "crypto/md5"
Matteo Scandolo6056e822019-11-13 14:05:29 -080023 "encoding/hex"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "encoding/json"
Girish Gowdracefae192020-03-19 18:14:10 -070025 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053026 "fmt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040027 "math/big"
Girish Gowdrafae935c2020-02-17 19:21:44 +053028 "strings"
William Kurkian740a09c2019-10-23 17:07:38 -040029 "sync"
Girish Gowdra3d633032019-12-10 16:37:05 +053030 "time"
Manikkaraj kb1d51442019-07-23 10:41:02 -040031
Esin Karamanccb714b2019-11-29 15:02:06 +000032 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v3/pkg/log"
34 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080035 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000036 "github.com/opencord/voltha-protos/v3/go/common"
37 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
38 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
39 openoltpb2 "github.com/opencord/voltha-protos/v3/go/openolt"
40 tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
41 "github.com/opencord/voltha-protos/v3/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040042
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040043 //deepcopy "github.com/getlantern/deepcopy"
Girish Gowdra3d633032019-12-10 16:37:05 +053044 "github.com/EagleChen/mapmutex"
Thomas Lee S94109f12020-03-03 16:39:29 +053045 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000046 "google.golang.org/grpc/codes"
47 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053048)
49
50const (
51 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070053 //HsiaFlow flow category
54 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053055
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070056 //EapolFlow flow category
57 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053058
Manikkaraj kb1d51442019-07-23 10:41:02 -040059 //DhcpFlow flow category
60 DhcpFlow = "DHCP_FLOW"
61
Esin Karamanccb714b2019-11-29 15:02:06 +000062 //MulticastFlow flow category
63 MulticastFlow = "MULTICAST_FLOW"
64
Esin Karamanae41e2b2019-12-17 18:13:13 +000065 //IgmpFlow flow category
66 IgmpFlow = "IGMP_FLOW"
67
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068 //IPProtoDhcp flow category
69 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053070
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070071 //IPProtoIgmp flow category
72 IPProtoIgmp = 2
73
74 //EapEthType eapethtype value
75 EapEthType = 0x888e
76 //LldpEthType lldp ethtype value
77 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000078 //IPv4EthType IPv4 ethernet type value
79 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070080
81 //IgmpProto proto value
82 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053083
Andrea Campanella7acc0b92020-02-14 09:20:49 +010084 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
85 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040086
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087 //DefaultMgmtVlan default vlan value
88 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053089
manikkaraj kbf256be2019-03-25 00:13:48 +053090 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070091
David K. Bainbridge82efc492019-09-04 09:57:11 -070092 //Upstream constant
93 Upstream = "upstream"
94 //Downstream constant
95 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000096 //Multicast constant
97 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070098 //PacketTagType constant
99 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700100 //Untagged constant
101 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700102 //SingleTag constant
103 SingleTag = "single_tag"
104 //DoubleTag constant
105 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +0530106
107 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108
109 //EthType constant
110 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +0000111 //EthDst constant
112 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113 //TPID constant
114 TPID = "tpid"
115 //IPProto constant
116 IPProto = "ip_proto"
117 //InPort constant
118 InPort = "in_port"
119 //VlanVid constant
120 VlanVid = "vlan_vid"
121 //VlanPcp constant
122 VlanPcp = "vlan_pcp"
123
124 //UDPDst constant
125 UDPDst = "udp_dst"
126 //UDPSrc constant
127 UDPSrc = "udp_src"
128 //Ipv4Dst constant
129 Ipv4Dst = "ipv4_dst"
130 //Ipv4Src constant
131 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700132 //Metadata constant
133 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700134 //TunnelID constant
135 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700136 //Output constant
137 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000138 //GroupID constant
139 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700140 // Actions
141
142 //PopVlan constant
143 PopVlan = "pop_vlan"
144 //PushVlan constant
145 PushVlan = "push_vlan"
146 //TrapToHost constant
147 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400148 //MaxMeterBand constant
149 MaxMeterBand = 2
150 //VlanPCPMask contant
151 VlanPCPMask = 0xFF
152 //VlanvIDMask constant
153 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000154 //IntfID constant
155 IntfID = "intfId"
156 //OnuID constant
157 OnuID = "onuId"
158 //UniID constant
159 UniID = "uniId"
160 //PortNo constant
161 PortNo = "portNo"
162 //AllocID constant
163 AllocID = "allocId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000164
165 //NoneOnuID constant
166 NoneOnuID = -1
167 //NoneUniID constant
168 NoneUniID = -1
169 //NoneGemPortID constant
170 NoneGemPortID = -1
Girish Gowdrafae935c2020-02-17 19:21:44 +0530171
172 // BinaryStringPrefix is binary string prefix
173 BinaryStringPrefix = "0b"
174 // BinaryBit1 is binary bit 1 expressed as a character
175 BinaryBit1 = '1'
manikkaraj kbf256be2019-03-25 00:13:48 +0530176)
177
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400178type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700179 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400180 gemPort uint32
181}
182
Girish Gowdra3d633032019-12-10 16:37:05 +0530183type pendingFlowDeleteKey struct {
184 intfID uint32
185 onuID uint32
186 uniID uint32
187}
188
189type tpLockKey struct {
190 intfID uint32
191 onuID uint32
192 uniID uint32
193}
194
Gamze Abakafee36392019-10-03 11:17:24 +0000195type schedQueue struct {
196 direction tp_pb.Direction
197 intfID uint32
198 onuID uint32
199 uniID uint32
200 tpID uint32
201 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700202 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000203 meterID uint32
204 flowMetadata *voltha.FlowMetadata
205}
206
Esin Karamanccb714b2019-11-29 15:02:06 +0000207type queueInfoBrief struct {
208 gemPortID uint32
209 servicePriority uint32
210}
211
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700212//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530213type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000214 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000215 deviceHandler *DeviceHandler
216 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000217 onuIdsLock sync.RWMutex
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530218 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
219 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700220 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
221 onuGemInfo [][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache, indexed by IntfId
222 onuGemInfoLock []sync.RWMutex // lock by Pon Port
223 pendingFlowDelete sync.Map
Girish Gowdra3d633032019-12-10 16:37:05 +0530224 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Esin Karamanccb714b2019-11-29 15:02:06 +0000225 perUserFlowHandleLock *mapmutex.Mutex
226 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 +0530227}
228
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700229//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
npujarec5762e2020-01-01 14:08:48 +0530230func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
Shrey Baid26912972020-04-16 21:02:31 +0530231 logger.Infow("initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530232 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530233 var err error
234 var idx uint32
235
manikkaraj kbf256be2019-03-25 00:13:48 +0530236 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530237 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000238 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530239 if err = flowMgr.populateTechProfilePerPonPort(); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530240 logger.Errorw("error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530241 return nil
242 }
William Kurkian740a09c2019-10-23 17:07:38 -0400243 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530244 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
245 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530246 ponPorts := rMgr.DevInfo.GetPonPorts()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700247 flowMgr.onuGemInfo = make([][]rsrcMgr.OnuGemInfo, ponPorts)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530248 //Load the onugem info cache from kv store on flowmanager start
249 for idx = 0; idx < ponPorts; idx++ {
npujarec5762e2020-01-01 14:08:48 +0530250 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530251 logger.Error("failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530252 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530253 //Load flowID list per gem map per interface from the kvstore.
npujarec5762e2020-01-01 14:08:48 +0530254 flowMgr.loadFlowIDlistForGem(ctx, idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530255 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700256 flowMgr.onuGemInfoLock = make([]sync.RWMutex, ponPorts)
Girish Gowdra3d633032019-12-10 16:37:05 +0530257 flowMgr.pendingFlowDelete = sync.Map{}
Girish Gowdrab77ded92020-04-08 11:45:05 -0700258 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(300, 100000000, 10000000, 1.1, 0.2)
Esin Karamanccb714b2019-11-29 15:02:06 +0000259 flowMgr.interfaceToMcastQueueMap = make(map[uint32]*queueInfoBrief)
260 //load interface to multicast queue map from kv store
npujarec5762e2020-01-01 14:08:48 +0530261 flowMgr.loadInterfaceToMulticastQueueMap(ctx)
Shrey Baid26912972020-04-16 21:02:31 +0530262 logger.Info("initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530263 return &flowMgr
264}
265
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700266func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700267 if direction == Upstream {
Shrey Baid26912972020-04-16 21:02:31 +0530268 logger.Debugw("upstream-flow-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700269 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700270 } else if direction == Downstream {
Shrey Baid26912972020-04-16 21:02:31 +0530271 logger.Debugw("downstream-flow-not-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700272 return uint64(flowID), nil
Esin Karamanccb714b2019-11-29 15:02:06 +0000273 } else if direction == Multicast {
Shrey Baid26912972020-04-16 21:02:31 +0530274 logger.Debugw("multicast-flow-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000275 return 0x2<<15 | uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400276 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530277 return 0, olterrors.NewErrInvalidValue(log.Fields{"direction": direction}, nil).Log()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400278 }
279}
280
npujarec5762e2020-01-01 14:08:48 +0530281func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Shrey Baid26912972020-04-16 21:02:31 +0530282 logger.Debugw("registering-flow-for-device ",
283 log.Fields{
284 "flow": flowFromCore,
285 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000286 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
287 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
288 if !ok {
289 flowIDList = []uint32{deviceFlow.FlowId}
290 }
291 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
292 f.flowsUsedByGemPort[gemPK] = flowIDList
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530293 // update the flowids for a gem to the KVstore
npujarec5762e2020-01-01 14:08:48 +0530294 f.resourceMgr.UpdateFlowIDsForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400295}
296
npujarec5762e2020-01-01 14:08:48 +0530297func (f *OpenOltFlowMgr) divideAndAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000298 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
299 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000300 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530301 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700302 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530303
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700304 logger.Infow("dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530305 "device-id": f.deviceHandler.device.Id,
306 "intf-id": intfID,
307 "onu-id": onuID,
308 "uni-id": uniID,
309 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700310 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530311 "action": actionInfo,
312 "usmeter-iD": UsMeterID,
313 "dsmeter-iD": DsMeterID,
314 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400315 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
316 // is because the flow is an NNI flow and there would be no onu resources associated with it
317 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400318 if onuID <= 0 {
Shrey Baid26912972020-04-16 21:02:31 +0530319 logger.Errorw("no-onu-id-for-flow",
320 log.Fields{
321 "port-no": portNo,
322 "classifer": classifierInfo,
323 "action": actionInfo,
324 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530325 return
326 }
327
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700328 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Shrey Baid26912972020-04-16 21:02:31 +0530329 logger.Debugw("uni-port-path", log.Fields{
330 "uni": uni,
331 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530332
333 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
334 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700335 logger.Debugw("dividing-flow-create-tcont-gem-ports", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530336 "device-id": f.deviceHandler.device.Id,
337 "intf-id": intfID,
338 "onu-id": onuID,
339 "uni-id": uniID,
340 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700341 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530342 "action": actionInfo,
343 "usmeter-id": UsMeterID,
344 "dsmeter-id": DsMeterID,
345 "tp-id": TpID})
npujarec5762e2020-01-01 14:08:48 +0530346 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530347 if allocID == 0 || gemPorts == nil || TpInst == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000348 logger.Error("alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530349 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
350 return
351 }
352 args := make(map[string]uint32)
353 args[IntfID] = intfID
354 args[OnuID] = onuID
355 args[UniID] = uniID
356 args[PortNo] = portNo
357 args[AllocID] = allocID
358
359 /* Flows can be added specific to gemport if p-bits are received.
360 * If no pbit mentioned then adding flows for all gemports
361 */
npujarec5762e2020-01-01 14:08:48 +0530362 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530363 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
364 } else {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700365 logger.Errorw("failed-to-acquire-per-user-flow-handle-lock",
Shrey Baid26912972020-04-16 21:02:31 +0530366 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700367 "intf-id": intfID,
368 "onu-id": onuID,
369 "uni-id": uniID,
370 "flow-id": flow.Id,
371 "flow-cookie": flow.Cookie,
372 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400373 return
374 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530375}
376
salmansiddiqui7ac62132019-08-22 03:58:50 +0000377// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530378func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400379
Shrey Baid26912972020-04-16 21:02:31 +0530380 logger.Debugw("CreateSchedulerQueues",
381 log.Fields{"dir": sq.direction,
382 "intf-id": sq.intfID,
383 "onu-id": sq.onuID,
384 "uni-id": sq.uniID,
385 "tp-id": sq.tpID,
386 "meter-id": sq.meterID,
387 "tp-inst": sq.tpInst,
388 "flowmetadata": sq.flowMetadata,
389 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400390
Gamze Abakafee36392019-10-03 11:17:24 +0000391 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000392 if err != nil {
393 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400394 }
395
396 /* Lets make a simple assumption that if the meter-id is present on the KV store,
397 * then the scheduler and queues configuration is applied on the OLT device
398 * in the given direction.
399 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000400
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530402 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400403 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530404 return olterrors.NewErrNotFound("meter",
405 log.Fields{"intf-id": sq.intfID,
406 "onu-id": sq.onuID,
407 "uni-id": sq.uniID,
408 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400409 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000410
Manikkaraj kb1d51442019-07-23 10:41:02 -0400411 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000412 if KvStoreMeter.MeterId == sq.meterID {
Shrey Baid26912972020-04-16 21:02:31 +0530413 logger.Debugw("scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400414 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400415 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530416 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800417 "unsupported": "meter-id",
418 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530419 "meter-id-in-flow": sq.meterID,
420 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400421 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000422
Shrey Baid26912972020-04-16 21:02:31 +0530423 logger.Debugw("meter-does-not-exist-creating-new",
424 log.Fields{
425 "meter-id": sq.meterID,
426 "direction": Direction,
427 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000428
Gamze Abakafee36392019-10-03 11:17:24 +0000429 if sq.direction == tp_pb.Direction_UPSTREAM {
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700430 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000431 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700432 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400433 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000434
435 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530436 return olterrors.NewErrNotFound("scheduler-config",
437 log.Fields{
438 "intf-id": sq.intfID,
439 "direction": sq.direction,
440 "tp-inst": sq.tpInst,
441 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000442 }
443
Manikkaraj kb1d51442019-07-23 10:41:02 -0400444 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000445 if sq.flowMetadata != nil {
446 for _, meter := range sq.flowMetadata.Meters {
447 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400448 meterConfig = meter
Shrey Baid26912972020-04-16 21:02:31 +0530449 logger.Debugw("found-meter-config-from-flowmetadata",
450 log.Fields{"meterConfig": meterConfig,
451 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400452 break
453 }
454 }
455 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530456 logger.Errorw("flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400457 }
458 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530459 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800460 "reason": "Could-not-get-meterbands-from-flowMetadata",
461 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530462 "meter-id": sq.meterID,
463 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400464 } else if len(meterConfig.Bands) < MaxMeterBand {
Shrey Baid26912972020-04-16 21:02:31 +0530465 logger.Errorw("invalid-number-of-bands-in-meter",
466 log.Fields{"Bands": meterConfig.Bands,
467 "meter-id": sq.meterID,
468 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530469 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800470 "reason": "Invalid-number-of-bands-in-meter",
471 "meterband-count": len(meterConfig.Bands),
472 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530473 "meter-id": sq.meterID,
474 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400475 }
476 cir := meterConfig.Bands[0].Rate
477 cbs := meterConfig.Bands[0].BurstSize
478 eir := meterConfig.Bands[1].Rate
479 ebs := meterConfig.Bands[1].BurstSize
480 pir := cir + eir
481 pbs := cbs + ebs
482 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
483
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700484 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000485 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400486
npujarec5762e2020-01-01 14:08:48 +0530487 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530488 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
489 log.Fields{"intf-id": sq.intfID,
490 "direction": sq.direction,
491 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400492 }
493
salmansiddiqui7ac62132019-08-22 03:58:50 +0000494 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400495 * store the meter id on the KV store, for further reference.
496 */
npujarec5762e2020-01-01 14:08:48 +0530497 if err := f.resourceMgr.UpdateMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530498 return olterrors.NewErrAdapter("failed-updating-meter-id",
499 log.Fields{"onu-id": sq.onuID,
500 "meter-id": sq.meterID,
501 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400502 }
Shrey Baid26912972020-04-16 21:02:31 +0530503 logger.Infow("updated-meter-info-into-kv-store-successfully",
504 log.Fields{"direction": Direction,
505 "Meter": meterConfig,
506 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400507 return nil
508}
509
npujarec5762e2020-01-01 14:08:48 +0530510func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000511
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700512 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000513
514 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530515 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
516 log.Fields{"intf-id": sq.intfID,
517 "direction": sq.direction,
518 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000519 }
520
Shrey Baid26912972020-04-16 21:02:31 +0530521 logger.Debugw("sending-traffic-scheduler-create-to-device",
522 log.Fields{
523 "direction": sq.direction,
524 "TrafficScheds": TrafficSched,
525 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530526 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000527 IntfId: sq.intfID, OnuId: sq.onuID,
528 UniId: sq.uniID, PortNo: sq.uniPort,
529 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000530 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000531 }
Shrey Baid26912972020-04-16 21:02:31 +0530532 logger.Infow("successfully-created-traffic-schedulers", log.Fields{
533 "direction": sq.direction,
534 "traffic-queues": trafficQueues,
535 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000536
537 // On receiving the CreateTrafficQueues request, the driver should create corresponding
538 // downstream queues.
Shrey Baid26912972020-04-16 21:02:31 +0530539 logger.Debugw("sending-traffic-queues-create-to-device",
540 log.Fields{"direction": sq.direction,
541 "traffic-queues": trafficQueues,
542 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530543 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000544 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
545 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000546 TrafficQueues: trafficQueues,
547 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530548 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000549 }
Shrey Baid26912972020-04-16 21:02:31 +0530550 logger.Infow("successfully-created-traffic-schedulers", log.Fields{
551 "direction": sq.direction,
552 "traffic-queues": trafficQueues,
553 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000554
Esin Karamanccb714b2019-11-29 15:02:06 +0000555 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700556 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000557 if len(multicastTrafficQueues) > 0 {
558 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
559 //assumed that there is only one queue per PON for the multicast service
560 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
561 //just put it in interfaceToMcastQueueMap to use for building group members
Shrey Baid26912972020-04-16 21:02:31 +0530562 logger.Debugw("multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000563 multicastQueuePerPonPort := multicastTrafficQueues[0]
564 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
565 gemPortID: multicastQueuePerPonPort.GemportId,
566 servicePriority: multicastQueuePerPonPort.Priority,
567 }
568 //also store the queue info in kv store
npujarec5762e2020-01-01 14:08:48 +0530569 f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID,
Esin Karamanccb714b2019-11-29 15:02:06 +0000570 multicastQueuePerPonPort.GemportId,
571 multicastQueuePerPonPort.Priority)
Shrey Baid26912972020-04-16 21:02:31 +0530572
573 logger.Infow("multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000574 }
575 }
576 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000577 return nil
578}
579
salmansiddiqui7ac62132019-08-22 03:58:50 +0000580// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530581func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400582
583 var Direction string
584 var SchedCfg *tp_pb.SchedulerConfig
585 var err error
Shrey Baid26912972020-04-16 21:02:31 +0530586 logger.Infow("removing-schedulers-and-queues-in-olt",
587 log.Fields{
588 "direction": sq.direction,
589 "intf-id": sq.intfID,
590 "onu-id": sq.onuID,
591 "uni-id": sq.uniID,
592 "uni-port": sq.uniPort,
593 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000594 if sq.direction == tp_pb.Direction_UPSTREAM {
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700595 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400596 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000597 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700598 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400599 Direction = "downstream"
600 }
601
Girish Kumar8f73fe02019-12-09 13:19:37 +0000602 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530603 return olterrors.NewErrNotFound("scheduler-config",
604 log.Fields{
605 "int-id": sq.intfID,
606 "direction": sq.direction,
607 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000608 }
609
npujarec5762e2020-01-01 14:08:48 +0530610 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400611 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530612 return olterrors.NewErrNotFound("meter",
613 log.Fields{
614 "onu-id": sq.onuID,
615 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400616 }
617 if KVStoreMeter == nil {
Shrey Baid26912972020-04-16 21:02:31 +0530618 logger.Warnw("no-meter-installed-yet",
619 log.Fields{
620 "direction": Direction,
621 "intf-id": sq.intfID,
622 "onu-id": sq.onuID,
623 "uni-id": sq.uniID,
624 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400625 return nil
626 }
627 cir := KVStoreMeter.Bands[0].Rate
628 cbs := KVStoreMeter.Bands[0].BurstSize
629 eir := KVStoreMeter.Bands[1].Rate
630 ebs := KVStoreMeter.Bands[1].BurstSize
631 pir := cir + eir
632 pbs := cbs + ebs
633
634 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
635
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700636 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000637 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000638
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700639 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000640 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530641 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
642 log.Fields{
643 "intf-id": sq.intfID,
644 "direction": sq.direction,
645 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000646 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400647
npujarec5762e2020-01-01 14:08:48 +0530648 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000649 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
650 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000651 TrafficQueues: TrafficQueues,
652 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000653 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530654 log.Fields{
655 "intf-id": sq.intfID,
656 "traffic-queues": TrafficQueues,
657 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400658 }
Shrey Baid26912972020-04-16 21:02:31 +0530659 logger.Infow("removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530660 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000661 IntfId: sq.intfID, OnuId: sq.onuID,
662 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400663 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000664 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530665 log.Fields{
666 "intf-id": sq.intfID,
667 "traffic-schedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400668 }
669
Shrey Baid26912972020-04-16 21:02:31 +0530670 logger.Infow("removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000671
672 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400673 * delete the meter id on the KV store.
674 */
npujarec5762e2020-01-01 14:08:48 +0530675 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400676 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530677 return olterrors.NewErrAdapter("unable-to-remove-meter",
678 log.Fields{
679 "onu": sq.onuID,
680 "meter": KVStoreMeter.MeterId,
681 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400682 }
Shrey Baid26912972020-04-16 21:02:31 +0530683 logger.Infow("removed-meter-from-KV-store-successfully",
684 log.Fields{
685 "meter-id": KVStoreMeter.MeterId,
686 "dir": Direction,
687 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400688 return err
689}
690
Gamze Abakafee36392019-10-03 11:17:24 +0000691// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700692func (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, interface{}) {
Gamze Abakafee36392019-10-03 11:17:24 +0000693 var allocIDs []uint32
694 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530695 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530696 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000697 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000698
npujarec5762e2020-01-01 14:08:48 +0530699 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
700 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400701
702 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530703
Shrey Baid26912972020-04-16 21:02:31 +0530704 logger.Debugw("creating-new-tcont-and-gem", log.Fields{
705 "intf-id": intfID,
706 "onu-id": onuID,
707 "uni-id": uniID,
708 "device-id": f.deviceHandler.device.Id,
709 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530710
Manikkaraj kb1d51442019-07-23 10:41:02 -0400711 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530712 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000713 if techProfileInstance == nil {
Shrey Baid26912972020-04-16 21:02:31 +0530714 logger.Infow("tp-instance-not-found--creating-new",
715 log.Fields{
716 "path": tpPath,
717 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530718 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000719 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530720 // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +0530721 logger.Errorw("tp-instance-create-failed",
722 log.Fields{
723 "error": err,
724 "tp-id": TpID,
725 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000726 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530727 }
npujarec5762e2020-01-01 14:08:48 +0530728 f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530729 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530730 logger.Debugw("tech-profile-instance-already-exist-for-given port-name",
731 log.Fields{
732 "uni": uni,
733 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530734 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530735 }
Gamze Abakafee36392019-10-03 11:17:24 +0000736
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700737 switch tpInst := techProfileInstance.(type) {
738 case *tp.TechProfile:
739 if UsMeterID != 0 {
740 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
741 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
742 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
743 logger.Errorw("CreateSchedulerQueues-failed-upstream",
744 log.Fields{
745 "error": err,
746 "meter-id": UsMeterID,
747 "device-id": f.deviceHandler.device.Id})
748 return 0, nil, nil
749 }
750 }
751 if DsMeterID != 0 {
752 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
753 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
754 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
755 logger.Errorw("CreateSchedulerQueues-failed-downstream",
756 log.Fields{
757 "error": err,
758 "meter-id": DsMeterID,
759 "device-id": f.deviceHandler.device.Id})
760 return 0, nil, nil
761 }
762 }
763 allocID := tpInst.UsScheduler.AllocID
764 for _, gem := range tpInst.UpstreamGemPortAttributeList {
765 gemPortIDs = append(gemPortIDs, gem.GemportID)
766 }
767 allocIDs = appendUnique(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000768
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700769 if tpInstanceExists {
770 return allocID, gemPortIDs, techProfileInstance
771 }
772
773 for _, gemPortID := range gemPortIDs {
774 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
775 }
776 logger.Infow("allocated-tcont-and-gem-ports",
777 log.Fields{
778 "alloc-ids": allocIDs,
779 "gemports": allgemPortIDs,
780 "device-id": f.deviceHandler.device.Id})
781 // Send Tconts and GEM ports to KV store
782 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530783 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700784 case *tp.EponProfile:
785 // CreateSchedulerQueues for EPON needs to be implemented here
786 // when voltha-protos for EPON is completed.
787 allocID := tpInst.AllocID
788 for _, gem := range tpInst.UpstreamQueueAttributeList {
789 gemPortIDs = append(gemPortIDs, gem.GemportID)
790 }
791 allocIDs = appendUnique(allocIDs, allocID)
792
793 if tpInstanceExists {
794 return allocID, gemPortIDs, techProfileInstance
795 }
796
797 for _, gemPortID := range gemPortIDs {
798 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
799 }
800 logger.Infow("allocated-tcont-and-gem-ports",
801 log.Fields{
802 "alloc-ids": allocIDs,
803 "gemports": allgemPortIDs,
804 "device-id": f.deviceHandler.device.Id})
805 // Send Tconts and GEM ports to KV store
806 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
807 return allocID, gemPortIDs, techProfileInstance
808 default:
809 logger.Errorw("unknown-tech",
810 log.Fields{
811 "tpInst": tpInst})
812 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530813 }
814
manikkaraj kbf256be2019-03-25 00:13:48 +0530815}
816
npujarec5762e2020-01-01 14:08:48 +0530817func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530818
Shrey Baid26912972020-04-16 21:02:31 +0530819 logger.Debugw("storing-allocated-tconts-and-gem-ports-into-KV-store",
820 log.Fields{
821 "intf-id": intfID,
822 "onu-id": onuID,
823 "uni-id": uniID,
824 "alloc-id": allocID,
825 "gemport-ids": gemPortIDs,
826 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530827 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530828 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530829 logger.Errorw("error-while-uploading-allocid-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530830 }
npujarec5762e2020-01-01 14:08:48 +0530831 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530832 logger.Errorw("error-while-uploading-gemports-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530833 }
npujarec5762e2020-01-01 14:08:48 +0530834 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530835 logger.Error("error-while-uploading-gemtopon-map-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530836 }
Shrey Baid26912972020-04-16 21:02:31 +0530837 logger.Infow("stored-tconts-and-gem-into-kv-store-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400838 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530839 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400840 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530841}
842
843func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000844 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530845 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000846 for _, intfID := range techRange.IntfIds {
847 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400848 tpCount++
Shrey Baid26912972020-04-16 21:02:31 +0530849 logger.Debugw("init-tech-profile-done",
850 log.Fields{
851 "intf-id": intfID,
852 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530853 }
854 }
855 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400856 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530857 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530858 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800859 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530860 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
861 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530862 }
Shrey Baid26912972020-04-16 21:02:31 +0530863 logger.Infow("populated-techprofile-for-ponports-successfully",
864 log.Fields{
865 "numofTech": tpCount,
866 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
867 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530868 return nil
869}
870
npujarec5762e2020-01-01 14:08:48 +0530871func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530872 portNo uint32, uplinkClassifier map[string]interface{},
873 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000874 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700875 uplinkClassifier[PacketTagType] = SingleTag
Shrey Baid26912972020-04-16 21:02:31 +0530876 logger.Debugw("adding-upstream-data-flow",
877 log.Fields{
878 "uplinkClassifier": uplinkClassifier,
879 "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800880 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000881 Upstream, logicalFlow, allocID, gemportID, tpID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530882 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530883}
884
npujarec5762e2020-01-01 14:08:48 +0530885func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530886 portNo uint32, downlinkClassifier map[string]interface{},
887 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000888 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700889 downlinkClassifier[PacketTagType] = DoubleTag
Shrey Baid26912972020-04-16 21:02:31 +0530890 logger.Debugw("adding-downstream-data-flow",
891 log.Fields{
892 "downlinkClassifier": downlinkClassifier,
893 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400894 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
895 if vlan, exists := downlinkClassifier[VlanVid]; exists {
896 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700897 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400898 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
Shrey Baid26912972020-04-16 21:02:31 +0530899 logger.Infow("ignoring-dl-trap-device-flow-from-core",
900 log.Fields{
901 "flow": logicalFlow,
902 "device-id": f.deviceHandler.device.Id,
903 "onu-id": onuID,
904 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800905 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400906 }
907 }
908 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530909 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400910
Manikkaraj k884c1242019-04-11 16:26:42 +0530911 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700912 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400913 // vlan_vid is a uint32. must be type asserted as such or conversion fails
914 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530915 if ok {
916 downlinkAction[VlanVid] = dlClVid & 0xfff
917 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530918 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530919 "reason": "failed-to-convert-vlanid-classifier",
920 "vlan-id": VlanVid,
921 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530922 }
923
David K. Bainbridge794735f2020-02-11 21:01:37 -0800924 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000925 Downstream, logicalFlow, allocID, gemportID, tpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530926}
927
npujarec5762e2020-01-01 14:08:48 +0530928func (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 +0530929 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000930 allocID uint32, gemPortID uint32, tpID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530931 /* One of the OLT platform (Broadcom BAL) requires that symmetric
932 flows require the same flow_id to be used across UL and DL.
933 Since HSIA flow is the only symmetric flow currently, we need to
934 re-use the flow_id across both direction. The 'flow_category'
935 takes priority over flow_cookie to find any available HSIA_FLOW
936 id for the ONU.
937 */
Shrey Baid26912972020-04-16 21:02:31 +0530938 logger.Infow("adding-hsia-flow",
939 log.Fields{
940 "intf-id": intfID,
941 "onu-id": onuID,
942 "uni-id": uniID,
943 "device-id": f.deviceHandler.device.Id,
944 "classifier": classifier,
945 "action": action,
946 "direction": direction,
947 "alloc-id": allocID,
948 "gemport-id": gemPortID,
949 "logicalflow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530950 var vlanPbit uint32 = 0xff // means no pbit
Gamze Abaka724d0852020-03-18 12:10:24 +0000951 var vlanVid uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400952 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000953 vlanPbit = classifier[VlanPcp].(uint32)
Shrey Baid26912972020-04-16 21:02:31 +0530954 logger.Debugw("found-pbit-in-flow",
955 log.Fields{
956 "vlan-pbit": vlanPbit,
957 "intf-id": intfID,
958 "onu-id": onuID,
959 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800960 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530961 logger.Debugw("pbit-not-found-in-flow",
962 log.Fields{
963 "vlan-pcp": VlanPcp,
964 "intf-id": intfID,
965 "onu-id": onuID,
966 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400967 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000968 if _, ok := classifier[VlanVid]; ok {
969 vlanVid = classifier[VlanVid].(uint32)
Shrey Baid26912972020-04-16 21:02:31 +0530970 log.Debugw("found-vlan-in-the-flow",
971 log.Fields{
972 "vlan-vid": vlanVid,
973 "intf-id": intfID,
974 "onu-id": onuID,
975 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000976 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700977 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530978 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +0530979 logger.Infow("flow-already-exists",
980 log.Fields{
981 "device-id": f.deviceHandler.device.Id,
982 "intf-id": intfID,
983 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800984 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530985 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000986 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530987 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530988 return olterrors.NewErrNotFound("hsia-flow-id",
989 log.Fields{
990 "direction": direction,
991 "device-id": f.deviceHandler.device.Id,
992 "intf-id": intfID,
993 "onu-id": onuID,
994 }, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530995 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800996 classifierProto, err := makeOpenOltClassifierField(classifier)
997 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530998 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530999 }
Shrey Baid26912972020-04-16 21:02:31 +05301000 logger.Debugw("created-classifier-proto",
1001 log.Fields{
1002 "classifier": *classifierProto,
1003 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001004 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001005 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301006 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301007 }
Shrey Baid26912972020-04-16 21:02:31 +05301008 logger.Debugw("created-action-proto",
1009 log.Fields{
1010 "action": *actionProto,
1011 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001012 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301013 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301014 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001015 log.Fields{
1016 "classifier": classifier,
1017 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301018 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001019 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301020 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001021 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
1022 OnuId: int32(onuID),
1023 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +00001024 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +05301025 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001026 AllocId: int32(allocID),
1027 NetworkIntfId: int32(networkIntfID),
1028 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +05301029 Classifier: classifierProto,
1030 Action: actionProto,
1031 Priority: int32(logicalFlow.Priority),
1032 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001033 PortNo: portNo,
1034 TechProfileId: tpID,
1035 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001036 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301037 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301038 }
Shrey Baid26912972020-04-16 21:02:31 +05301039 logger.Infow("hsia-flow-added-to-device-successfully",
1040 log.Fields{"direction": direction,
1041 "device-id": f.deviceHandler.device.Id,
1042 "flow": flow,
1043 "intf-id": intfID,
1044 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001045 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
1046 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1047 flow.OnuId,
1048 flow.UniId,
1049 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301050 return olterrors.NewErrPersistence("update", "flow", flowID,
1051 log.Fields{
1052 "flow": flow,
1053 "device-id": f.deviceHandler.device.Id,
1054 "intf-id": intfID,
1055 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001056 }
1057 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301058}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001059
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001060func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1061 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1062 gemPortID uint32, tpID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301063
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301064 networkIntfID, err := getNniIntfID(classifier, action)
1065 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301066 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001067 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301068 "action": action,
1069 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001070 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301071 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301072
1073 // Clear the action map
1074 for k := range action {
1075 delete(action, k)
1076 }
1077
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001078 action[TrapToHost] = true
1079 classifier[UDPSrc] = uint32(68)
1080 classifier[UDPDst] = uint32(67)
1081 classifier[PacketTagType] = SingleTag
1082 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301083
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001084 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301085 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301086 logger.Infow("flow-exists--not-re-adding",
1087 log.Fields{
1088 "device-id": f.deviceHandler.device.Id,
1089 "intf-id": intfID,
1090 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001091 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301092 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301093
David K. Bainbridge794735f2020-02-11 21:01:37 -08001094 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 +05301095
1096 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301097 return olterrors.NewErrNotFound("flow",
1098 log.Fields{
1099 "interface-id": intfID,
1100 "gem-port": gemPortID,
1101 "cookie": flowStoreCookie,
1102 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001103 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301104 }
1105
Shrey Baid26912972020-04-16 21:02:31 +05301106 logger.Debugw("creating-ul-dhcp-flow",
1107 log.Fields{
1108 "ul_classifier": classifier,
1109 "ul_action": action,
1110 "uplinkFlowId": flowID,
1111 "intf-id": intfID,
1112 "onu-id": onuID,
1113 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301114
David K. Bainbridge794735f2020-02-11 21:01:37 -08001115 classifierProto, err := makeOpenOltClassifierField(classifier)
1116 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301117 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301118 }
Shrey Baid26912972020-04-16 21:02:31 +05301119 logger.Debugw("created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001120 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001121 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301122 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301123 }
1124
David K. Bainbridge794735f2020-02-11 21:01:37 -08001125 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001126 OnuId: int32(onuID),
1127 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301128 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001129 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001130 AllocId: int32(allocID),
1131 NetworkIntfId: int32(networkIntfID),
1132 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301133 Classifier: classifierProto,
1134 Action: actionProto,
1135 Priority: int32(logicalFlow.Priority),
1136 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001137 PortNo: portNo,
1138 TechProfileId: tpID,
1139 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001140 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301141 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001142 }
Shrey Baid26912972020-04-16 21:02:31 +05301143 logger.Infow("dhcp-ul-flow-added-to-device-successfully",
1144 log.Fields{
1145 "device-id": f.deviceHandler.device.Id,
1146 "flow-id": flowID,
1147 "intf-id": intfID,
1148 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001149 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
1150 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
1151 dhcpFlow.OnuId,
1152 dhcpFlow.UniId,
1153 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301154 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1155 log.Fields{
1156 "flow": dhcpFlow,
1157 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301158 }
1159
David K. Bainbridge794735f2020-02-11 21:01:37 -08001160 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301161}
1162
Esin Karamanae41e2b2019-12-17 18:13:13 +00001163//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301164func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001165 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32) error {
1166 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001167}
1168
1169//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301170func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001171 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string, tpID uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001172
1173 networkIntfID, err := getNniIntfID(classifier, action)
1174 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301175 return olterrors.NewErrNotFound("nni-interface-id",
1176 log.Fields{
1177 "classifier": classifier,
1178 "action": action,
1179 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001180 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001181 }
1182
1183 // Clear the action map
1184 for k := range action {
1185 delete(action, k)
1186 }
1187
1188 action[TrapToHost] = true
1189 classifier[PacketTagType] = SingleTag
1190 delete(classifier, VlanVid)
1191
1192 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301193 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301194 logger.Infow("flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001195 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001196 }
1197
npujarec5762e2020-01-01 14:08:48 +05301198 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 +00001199
1200 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301201 return olterrors.NewErrNotFound("flow-id",
1202 log.Fields{
1203 "intf-id": intfID,
1204 "oni-id": onuID,
1205 "cookie": flowStoreCookie,
1206 "flow-type": flowType,
1207 "device-id": f.deviceHandler.device.Id,
1208 "onu-id": onuID},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001209 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001210 }
1211
Shrey Baid26912972020-04-16 21:02:31 +05301212 logger.Debugw("creating-upstream-trap-flow",
1213 log.Fields{
1214 "ul_classifier": classifier,
1215 "ul_action": action,
1216 "uplinkFlowId": flowID,
1217 "flowType": flowType,
1218 "device-id": f.deviceHandler.device.Id,
1219 "intf-id": intfID,
1220 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001221
David K. Bainbridge794735f2020-02-11 21:01:37 -08001222 classifierProto, err := makeOpenOltClassifierField(classifier)
1223 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301224 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001225 }
Shrey Baid26912972020-04-16 21:02:31 +05301226 logger.Debugw("created-classifier-proto",
1227 log.Fields{
1228 "classifier": *classifierProto,
1229 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001230 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001231 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301232 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001233 }
1234
David K. Bainbridge794735f2020-02-11 21:01:37 -08001235 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001236 OnuId: int32(onuID),
1237 UniId: int32(uniID),
1238 FlowId: flowID,
1239 FlowType: Upstream,
1240 AllocId: int32(allocID),
1241 NetworkIntfId: int32(networkIntfID),
1242 GemportId: int32(gemPortID),
1243 Classifier: classifierProto,
1244 Action: actionProto,
1245 Priority: int32(logicalFlow.Priority),
1246 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001247 PortNo: portNo,
1248 TechProfileId: tpID,
1249 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001250
David K. Bainbridge794735f2020-02-11 21:01:37 -08001251 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301252 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001253 }
Shrey Baid26912972020-04-16 21:02:31 +05301254 logger.Infof("%s ul-flow-added-to-device-successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001255
David K. Bainbridge794735f2020-02-11 21:01:37 -08001256 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
1257 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1258 flow.OnuId,
1259 flow.UniId,
1260 flow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301261 return olterrors.NewErrPersistence("update", "flow", flow.FlowId, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001262 }
1263
David K. Bainbridge794735f2020-02-11 21:01:37 -08001264 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001265}
1266
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001267// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001268func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1269 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1270 gemPortID uint32, vlanID uint32, tpID uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05301271 logger.Infow("adding-eapol-to-device",
1272 log.Fields{
1273 "intf-id": intfID,
1274 "onu-id": onuID,
1275 "port-no": portNo,
1276 "alloc-id": allocID,
1277 "gemport-id": gemPortID,
1278 "vlan-id": vlanID,
1279 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301280
1281 uplinkClassifier := make(map[string]interface{})
1282 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301283
manikkaraj kbf256be2019-03-25 00:13:48 +05301284 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001285 uplinkClassifier[EthType] = uint32(EapEthType)
1286 uplinkClassifier[PacketTagType] = SingleTag
1287 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001288 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301289 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001290 uplinkAction[TrapToHost] = true
1291 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301292 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301293 logger.Infow("flow-exists-not-re-adding", log.Fields{
1294 "device-id": f.deviceHandler.device.Id,
1295 "onu-id": onuID,
1296 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001297 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301298 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301299 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +00001300 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +05301301 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301302 return olterrors.NewErrNotFound("flow-id",
1303 log.Fields{
1304 "intf-id": intfID,
1305 "onu-id": onuID,
1306 "coookie": flowStoreCookie,
1307 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001308 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301309 }
Shrey Baid26912972020-04-16 21:02:31 +05301310 logger.Debugw("creating-ul-eapol-flow",
1311 log.Fields{
1312 "ul_classifier": uplinkClassifier,
1313 "ul_action": uplinkAction,
1314 "uplinkFlowId": uplinkFlowID,
1315 "device-id": f.deviceHandler.device.Id,
1316 "intf-id": intfID,
1317 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301318
David K. Bainbridge794735f2020-02-11 21:01:37 -08001319 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1320 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301321 return olterrors.NewErrInvalidValue(log.Fields{
1322 "classifier": uplinkClassifier,
1323 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301324 }
Shrey Baid26912972020-04-16 21:02:31 +05301325 logger.Debugw("created-classifier-proto",
1326 log.Fields{
1327 "classifier": *classifierProto,
1328 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001329 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001330 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301331 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301332 }
Shrey Baid26912972020-04-16 21:02:31 +05301333 logger.Debugw("created-action-proto",
1334 log.Fields{
1335 "action": *actionProto,
1336 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001337 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301338 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301339 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001340 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301341 "action": action,
1342 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001343 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301344 }
1345
David K. Bainbridge794735f2020-02-11 21:01:37 -08001346 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001347 OnuId: int32(onuID),
1348 UniId: int32(uniID),
1349 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001350 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001351 AllocId: int32(allocID),
1352 NetworkIntfId: int32(networkIntfID),
1353 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301354 Classifier: classifierProto,
1355 Action: actionProto,
1356 Priority: int32(logicalFlow.Priority),
1357 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001358 PortNo: portNo,
1359 TechProfileId: tpID,
1360 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001361 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301362 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001363 }
Shrey Baid26912972020-04-16 21:02:31 +05301364 logger.Infow("eapol-ul-flow-added-to-device-successfully",
1365 log.Fields{
1366 "device-id": f.deviceHandler.device.Id,
1367 "onu-id": onuID,
1368 "intf-id": intfID,
1369 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001370 flowCategory := "EAPOL"
1371 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1372 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1373 upstreamFlow.OnuId,
1374 upstreamFlow.UniId,
1375 upstreamFlow.FlowId,
1376 /* lowCategory, */
1377 flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301378 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1379 log.Fields{
1380 "flow": upstreamFlow,
1381 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301382 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001383 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301384}
1385
David K. Bainbridge794735f2020-02-11 21:01:37 -08001386func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001387 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001388
1389 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1390 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1391 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001392 if vlanID != ReservedVlan {
1393 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001394 classifier.OVid = vid
1395 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301396 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001397 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1398 vid := uint32(metadata)
1399 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001400 classifier.IVid = vid
1401 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301402 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301403 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001404 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301405 classifier.OPbits = vlanPcp
1406 } else {
1407 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301408 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001409 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1410 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1411 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1412 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001413 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001414 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1415 classifier.PktTagType = pktTagType
1416
1417 switch pktTagType {
1418 case SingleTag:
1419 case DoubleTag:
1420 case Untagged:
1421 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001422 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301423 }
1424 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001425 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301426}
1427
Gamze Abaka724d0852020-03-18 12:10:24 +00001428func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001429 var actionCmd openoltpb2.ActionCmd
1430 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301431 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001432 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301433 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001434 if _, ok := actionInfo[VlanPcp]; ok {
1435 action.Cmd.RemarkInnerPbits = true
1436 action.IPbits = actionInfo[VlanPcp].(uint32)
1437 if _, ok := actionInfo[VlanVid]; ok {
1438 action.Cmd.TranslateInnerTag = true
1439 action.IVid = actionInfo[VlanVid].(uint32)
1440 }
1441 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001442 } else if _, ok := actionInfo[PushVlan]; ok {
1443 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301444 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001445 if _, ok := actionInfo[VlanPcp]; ok {
1446 action.OPbits = actionInfo[VlanPcp].(uint32)
1447 action.Cmd.RemarkOuterPbits = true
1448 if _, ok := classifierInfo[VlanVid]; ok {
1449 action.IVid = classifierInfo[VlanVid].(uint32)
1450 action.Cmd.TranslateInnerTag = true
1451 }
1452 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001453 } else if _, ok := actionInfo[TrapToHost]; ok {
1454 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301455 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001456 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301457 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001458 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301459}
1460
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001461// getTPpath return the ETCD path for a given UNI port
1462func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uniPath string, TpID uint32) string {
1463 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301464}
1465
Gamze Abakafee36392019-10-03 11:17:24 +00001466// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301467func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1468 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001469 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1470
Gamze Abakafee36392019-10-03 11:17:24 +00001471 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301472 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301473 olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301474 // return err
1475 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001476 }
Shrey Baid26912972020-04-16 21:02:31 +05301477 log.Debugw("tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001478 }
1479 return nil
1480}
1481
1482// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301483func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001484 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001485 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001486 }
npujarec5762e2020-01-01 14:08:48 +05301487 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301488 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1489 log.Fields{
1490 "tp-id": tpID,
1491 "uni-port-name": uniPortName,
1492 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001493 }
1494 return nil
1495}
1496
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001497func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301498 if len(classifier) == 0 { // should never happen
Shrey Baid26912972020-04-16 21:02:31 +05301499 logger.Error("invalid-classfier-object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301500 return 0
1501 }
Shrey Baid26912972020-04-16 21:02:31 +05301502 logger.Debugw("generating-flow-store-cookie",
1503 log.Fields{
1504 "classifier": classifier,
1505 "gemport-id": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301506 var jsonData []byte
1507 var flowString string
1508 var err error
1509 // TODO: Do we need to marshall ??
1510 if jsonData, err = json.Marshal(classifier); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301511 logger.Error("failed-to-encode-classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301512 return 0
1513 }
1514 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001515 if gemPortID != 0 {
1516 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301517 }
1518 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001519 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301520 hash := big.NewInt(0)
1521 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301522 generatedHash := hash.Uint64()
Shrey Baid26912972020-04-16 21:02:31 +05301523 logger.Debugw("hash-generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301524 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301525}
1526
npujarec5762e2020-01-01 14:08:48 +05301527func (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 +05301528 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001529 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001530 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1531 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1532 */
1533 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001534 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001535 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001536 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001537 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001538 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301539 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001540 if existingFlows != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301541 logger.Debugw("flow-exists-for-given-flowID--appending-it-to-current-flow",
1542 log.Fields{
1543 "flow-id": flow.FlowId,
1544 "device-id": f.deviceHandler.device.Id,
1545 "intf-id": intfID,
1546 "onu-id": flow.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001547 //for _, f := range *existingFlows {
1548 // flows = append(flows, f)
1549 //}
1550 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001551 }
Shrey Baid26912972020-04-16 21:02:31 +05301552 logger.Debugw("updated-flows-for-given-flowID-and-onuid",
1553 log.Fields{
1554 "updatedflow": flows,
1555 "flow-id": flow.FlowId,
1556 "onu-id": flow.OnuId,
1557 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +05301558 return &flows
1559}
1560
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001561//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1562// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1563// var intfId uint32
1564// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1565// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1566// */
1567// if flow.AccessIntfId != -1 {
1568// intfId = uint32(flow.AccessIntfId)
1569// } else {
1570// intfId = uint32(flow.NetworkIntfId)
1571// }
1572// // Get existing flows matching flowid for given subscriber from KV store
1573// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1574// if existingFlows != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001575// logger.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001576// for _, f := range *existingFlows {
1577// flows = append(flows, f)
1578// }
1579// }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001580// logger.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001581// return &flows
1582//}
1583
npujarec5762e2020-01-01 14:08:48 +05301584func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(ctx context.Context, intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
Shrey Baid26912972020-04-16 21:02:31 +05301585 logger.Debugw("storing-flow(s)-into-kv-store", log.Fields{
1586 "flow-id": flowID,
1587 "device-id": f.deviceHandler.device.Id,
1588 "intf-id": intfID,
1589 "onu-id": onuID})
npujarec5762e2020-01-01 14:08:48 +05301590 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301591 logger.Warnw("error-while-storing-flow-into-kv-store", log.Fields{
1592 "device-id": f.deviceHandler.device.Id,
1593 "onu-id": onuID,
1594 "intf-id": intfID,
1595 "flow-id": flowID})
manikkaraj k17652a72019-05-06 09:06:36 -04001596 return err
1597 }
Shrey Baid26912972020-04-16 21:02:31 +05301598 logger.Infow("stored-flow(s)-into-kv-store-successfully!", log.Fields{
1599 "device-id": f.deviceHandler.device.Id,
1600 "onu-id": onuID,
1601 "intf-id": intfID,
1602 "flow-id": flowID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301603 return nil
1604}
1605
David K. Bainbridge794735f2020-02-11 21:01:37 -08001606func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001607
1608 var intfID uint32
1609 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1610 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1611 */
1612 if deviceFlow.AccessIntfId != -1 {
1613 intfID = uint32(deviceFlow.AccessIntfId)
1614 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001615 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001616 intfID = uint32(deviceFlow.NetworkIntfId)
1617 }
1618
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001619 logger.Debugw("sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301620 "flow": *deviceFlow,
1621 "device-id": f.deviceHandler.device.Id,
1622 "intf-id": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301623 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001624
1625 st, _ := status.FromError(err)
1626 if st.Code() == codes.AlreadyExists {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001627 logger.Debug("flow-already-exists", log.Fields{
1628 "err": err,
1629 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301630 "device-id": f.deviceHandler.device.Id,
1631 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001632 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301633 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001634
1635 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301636 logger.Errorw("failed-to-add-flow-to-device",
1637 log.Fields{"err": err,
1638 "device-flow": deviceFlow,
1639 "device-id": f.deviceHandler.device.Id,
1640 "intf-id": intfID})
npujarec5762e2020-01-01 14:08:48 +05301641 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001642 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001643 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301644 if deviceFlow.GemportId != -1 {
1645 // No need to register the flow if it is a trap on nni flow.
npujarec5762e2020-01-01 14:08:48 +05301646 f.registerFlow(ctx, logicalFlow, deviceFlow)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301647 }
Shrey Baid26912972020-04-16 21:02:31 +05301648 logger.Infow("flow-added-to-device-successfully ",
1649 log.Fields{
1650 "flow": *deviceFlow,
1651 "device-id": f.deviceHandler.device.Id,
1652 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001653 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001654}
1655
Matteo Scandolo92186242020-06-12 10:54:18 -07001656func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
Shrey Baid26912972020-04-16 21:02:31 +05301657 logger.Debugw("sending-flow-to-device-via-grpc",
1658 log.Fields{
1659 "flow": *deviceFlow,
1660 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001661 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1662 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001663 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Shrey Baid26912972020-04-16 21:02:31 +05301664 logger.Warnw("can-not-remove-flow-from-device--unreachable",
1665 log.Fields{
1666 "err": err,
1667 "deviceFlow": deviceFlow,
1668 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001669 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001670 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001671 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001672 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001673
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001674 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001675 logger.Infow("flow-removed-from-device-successfully", log.Fields{
1676 "of-flow-id": ofFlowID,
1677 "flow": *deviceFlow,
1678 "device-id": f.deviceHandler.device.Id,
1679 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001680 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301681}
1682
1683/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1684 //update core flows_proxy : flows_proxy.update('/', flows)
1685}
1686
1687func generateStoredId(flowId uint32, direction string)uint32{
1688
David K. Bainbridge82efc492019-09-04 09:57:11 -07001689 if direction == Upstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001690 logger.Debug("Upstream flow shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301691 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001692 }else if direction == Downstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001693 logger.Debug("Downstream flow not shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301694 return flowId
1695 }else{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001696 logger.Errorw("Unrecognized direction",log.Fields{"direction": direction})
manikkaraj kbf256be2019-03-25 00:13:48 +05301697 return flowId
1698 }
1699}
1700
1701*/
1702
David K. Bainbridge794735f2020-02-11 21:01:37 -08001703func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001704
1705 classifierInfo := make(map[string]interface{})
1706 actionInfo := make(map[string]interface{})
1707
1708 classifierInfo[EthType] = uint32(LldpEthType)
1709 classifierInfo[PacketTagType] = Untagged
1710 actionInfo[TrapToHost] = true
1711
1712 // LLDP flow is installed to trap LLDP packets on the NNI port.
1713 // We manage flow_id resource pool on per PON port basis.
1714 // Since this situation is tricky, as a hack, we pass the NNI port
1715 // index (network_intf_id) as PON port Index for the flow_id resource
1716 // pool. Also, there is no ONU Id available for trapping LLDP packets
1717 // on NNI port, use onu_id as -1 (invalid)
1718 // ****************** CAVEAT *******************
1719 // This logic works if the NNI Port Id falls within the same valid
1720 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1721 // we need to have a re-look at this.
1722 // *********************************************
1723
1724 var onuID = -1
1725 var uniID = -1
1726 var gemPortID = -1
1727
David K. Bainbridge794735f2020-02-11 21:01:37 -08001728 networkInterfaceID, err := IntfIDFromNniPortNum(portNo)
1729 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301730 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001731 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001732 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301733 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301734 logger.Infow("flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001735 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001736 }
npujarec5762e2020-01-01 14:08:48 +05301737 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001738
1739 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301740 return olterrors.NewErrNotFound("flow-id",
1741 log.Fields{
1742 "interface-id": networkInterfaceID,
1743 "onu-id": onuID,
1744 "uni-id": uniID,
1745 "gem-port-id": gemPortID,
1746 "cookie": flowStoreCookie,
1747 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001748 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001749 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001750 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1751 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301752 return olterrors.NewErrInvalidValue(
1753 log.Fields{
1754 "classifier": classifierInfo,
1755 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001756 }
Shrey Baid26912972020-04-16 21:02:31 +05301757 logger.Debugw("created-classifier-proto",
1758 log.Fields{
1759 "classifier": *classifierProto,
1760 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001761 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001762 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301763 return olterrors.NewErrInvalidValue(
1764 log.Fields{
1765 "action": actionInfo,
1766 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001767 }
Shrey Baid26912972020-04-16 21:02:31 +05301768 logger.Debugw("created-action-proto",
1769 log.Fields{
1770 "action": *actionProto,
1771 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001772
1773 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1774 OnuId: int32(onuID), // OnuId not required
1775 UniId: int32(uniID), // UniId not used
1776 FlowId: flowID,
1777 FlowType: Downstream,
1778 NetworkIntfId: int32(networkInterfaceID),
1779 GemportId: int32(gemPortID),
1780 Classifier: classifierProto,
1781 Action: actionProto,
1782 Priority: int32(flow.Priority),
1783 Cookie: flow.Cookie,
1784 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001785 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301786 return olterrors.NewErrFlowOp("add", flowID,
1787 log.Fields{
1788 "flow": downstreamflow,
1789 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001790 }
Shrey Baid26912972020-04-16 21:02:31 +05301791 logger.Infow("lldp-trap-on-nni-flow-added-to-device-successfully",
1792 log.Fields{
1793 "device-id": f.deviceHandler.device.Id,
1794 "onu-id": onuID,
1795 "flow-id": flowID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001796 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1797 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1798 int32(onuID),
1799 int32(uniID),
1800 flowID, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301801 return olterrors.NewErrPersistence("update", "flow", flowID,
1802 log.Fields{
1803 "flow": downstreamflow,
1804 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001805 }
1806 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301807}
1808
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001809func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1810 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001811}
1812
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001813//getOnuDevice to fetch onu from cache or core.
1814func (f *OpenOltFlowMgr) getOnuDevice(intfID uint32, onuID uint32) (*OnuDevice, error) {
1815 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1816 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1817 if !ok {
Shrey Baid26912972020-04-16 21:02:31 +05301818 logger.Debugw("couldnt-find-onu-in-cache",
1819 log.Fields{
1820 "intf-id": intfID,
1821 "onu-id": onuID,
1822 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001823 onuDevice, err := f.getChildDevice(intfID, onuID)
1824 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301825 return nil, olterrors.NewErrNotFound("onu-child-device",
1826 log.Fields{
1827 "onu-id": onuID,
1828 "intf-id": intfID,
1829 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001830 }
1831 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1832 //better to ad the device to cache here.
1833 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1834 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301835 logger.Debugw("found-onu-in-cache",
1836 log.Fields{
1837 "intf-id": intfID,
1838 "onu-id": onuID,
1839 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001840 }
1841
1842 return onuDev.(*OnuDevice), nil
1843}
1844
1845//getChildDevice to fetch onu
1846func (f *OpenOltFlowMgr) getChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
Shrey Baid26912972020-04-16 21:02:31 +05301847 logger.Infow("GetChildDevice",
1848 log.Fields{
1849 "pon-port": intfID,
1850 "onu-id": onuID,
1851 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001852 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001853 onuDevice, err := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
1854 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301855 return nil, olterrors.NewErrNotFound("onu",
1856 log.Fields{
1857 "interface-id": parentPortNo,
1858 "onu-id": onuID,
1859 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001860 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301861 }
Shrey Baid26912972020-04-16 21:02:31 +05301862 logger.Infow("successfully-received-child-device-from-core",
1863 log.Fields{
1864 "device-id": f.deviceHandler.device.Id,
1865 "child_device_id": onuDevice.Id,
1866 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301867 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301868}
1869
1870func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Shrey Baid26912972020-04-16 21:02:31 +05301871 logger.Info("unimplemented-flow %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301872 return nil
1873}
1874
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001875func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
Shrey Baid26912972020-04-16 21:02:31 +05301876 logger.Info("unimplemented-device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301877}
1878
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001879func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001880 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001881 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001882 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001883 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001884}
1885
Girish Gowdra6b130582019-11-20 16:45:20 +05301886func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001887 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301888 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301889 logger.Debugw("couldnt-find-onu-child-device",
1890 log.Fields{
1891 "intf-id": intfID,
1892 "onu-id": onuID,
1893 "uni-id": uniID,
1894 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001895 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301896 }
1897
1898 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Shrey Baid26912972020-04-16 21:02:31 +05301899 logger.Debugw("sending-gem-port-delete-to-openonu-adapter",
1900 log.Fields{
1901 "msg": *delGemPortMsg,
1902 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301903 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1904 delGemPortMsg,
1905 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301906 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001907 onuDev.deviceType,
1908 onuDev.deviceID,
1909 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301910 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1911 log.Fields{
1912 "from-adapter": f.deviceHandler.device.Type,
1913 "to-adapter": onuDev.deviceType,
1914 "onu-id": onuDev.deviceID,
1915 "proxyDeviceID": onuDev.proxyDeviceID,
1916 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301917 }
Shrey Baid26912972020-04-16 21:02:31 +05301918 logger.Infow("success-sending-del-gem-port-to-onu-adapter",
1919 log.Fields{
1920 "msg": delGemPortMsg,
1921 "from-adapter": f.deviceHandler.device.Type,
1922 "to-adapter": onuDev.deviceType,
1923 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301924 return nil
1925}
1926
1927func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001928 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301929 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301930 logger.Warnw("couldnt-find-onu-child-device",
1931 log.Fields{
1932 "intf-id": intfID,
1933 "onu-id": onuID,
1934 "uni-id": uniID,
1935 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001936 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301937 }
1938
1939 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Shrey Baid26912972020-04-16 21:02:31 +05301940 logger.Debugw("sending-tcont-delete-to-openonu-adapter",
1941 log.Fields{
1942 "msg": *delTcontMsg,
1943 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301944 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1945 delTcontMsg,
1946 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301947 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001948 onuDev.deviceType,
1949 onuDev.deviceID,
1950 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301951 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1952 log.Fields{
1953 "from-adapter": f.deviceHandler.device.Type,
1954 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1955 "proxyDeviceID": onuDev.proxyDeviceID,
1956 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301957 }
Shrey Baid26912972020-04-16 21:02:31 +05301958 logger.Infow("success-sending-del-tcont-to-onu-adapter",
1959 log.Fields{
1960 "msg": delTcontMsg,
1961 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301962 return nil
1963}
1964
Girish Gowdra3d633032019-12-10 16:37:05 +05301965func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1966 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1967 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1968 if val.(int) > 0 {
1969 pnFlDels := val.(int) - 1
1970 if pnFlDels > 0 {
Shrey Baid26912972020-04-16 21:02:31 +05301971 logger.Debugw("flow-delete-succeeded--more-pending",
1972 log.Fields{
1973 "intf": Intf,
1974 "onu-id": onuID,
1975 "uni-id": uniID,
1976 "currpendingflowcnt": pnFlDels,
1977 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301978 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1979 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301980 logger.Debugw("all-pending-flow-deletes-handled--removing-entry-from-map",
1981 log.Fields{
1982 "intf": Intf,
1983 "onu-id": onuID,
1984 "uni-id": uniID,
1985 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301986 f.pendingFlowDelete.Delete(pnFlDelKey)
1987 }
1988 }
1989 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301990 logger.Debugw("no-pending-delete-flows-found",
1991 log.Fields{
1992 "intf": Intf,
1993 "onu-id": onuID,
1994 "uni-id": uniID,
1995 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301996
1997 }
1998
1999}
2000
Girish Gowdrac3037402020-01-22 20:29:53 +05302001// Once the gemport is released for a given onu, it also has to be cleared from local cache
2002// which was used for deriving the gemport->logicalPortNo during packet-in.
2003// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
2004// is conveyed to ONOS during packet-in OF message.
2005func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002006
2007 f.onuGemInfoLock[intfID].Lock()
2008 defer f.onuGemInfoLock[intfID].Unlock()
2009
Shrey Baid26912972020-04-16 21:02:31 +05302010 logger.Infow("deleting-gem-from-local-cache",
2011 log.Fields{
2012 "gem": gemPortID,
2013 "intf-id": intfID,
2014 "onu-id": onuID,
2015 "device-id": f.deviceHandler.device.Id,
2016 "onu-gem": f.onuGemInfo[intfID]})
Girish Gowdrac3037402020-01-22 20:29:53 +05302017 onugem := f.onuGemInfo[intfID]
serkant.uluderya96af4932020-02-20 16:58:48 -08002018 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05302019 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08002020 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05302021 // If the gemport is found, delete it from local cache.
2022 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08002023 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
2024 onugem[i] = onu
Shrey Baid26912972020-04-16 21:02:31 +05302025 logger.Infow("removed-gemport-from-local-cache",
2026 log.Fields{
2027 "intf-id": intfID,
2028 "onu-id": onuID,
2029 "deletedgemport-id": gemPortID,
2030 "gemports": onu.GemPorts,
2031 "device-id": f.deviceHandler.device.Id})
Girish Gowdrac3037402020-01-22 20:29:53 +05302032 break
2033 }
2034 }
2035 break
2036 }
2037 }
2038}
2039
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302040//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002041// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302042func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302043 gemPortID int32, flowID uint32, flowDirection string,
2044 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002045
Chaitrashree G S90a17952019-11-14 21:51:21 -05002046 tpID, err := getTpIDFromFlow(flow)
2047 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302048 return olterrors.NewErrNotFound("tp-id",
2049 log.Fields{
2050 "flow": flow,
2051 "intf": Intf,
2052 "onu-id": onuID,
2053 "uni-id": uniID,
2054 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002055 }
Gamze Abakafee36392019-10-03 11:17:24 +00002056
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002057 if len(updatedFlows) >= 0 {
2058 // There are still flows referencing the same flow_id.
2059 // So the flow should not be freed yet.
2060 // For ex: Case of HSIA where same flow is shared
2061 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00002062 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302063 olterrors.NewErrPersistence("update", "flow", flowID,
2064 log.Fields{
2065 "flow": updatedFlows,
2066 "device-id": f.deviceHandler.device.Id}, err).Log()
Girish Kumarf26e4882020-03-05 06:49:10 +00002067 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002068 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05302069 // Do this for subscriber flows only (not trap from NNI flows)
2070 if onuID != -1 && uniID != -1 {
2071 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
2072 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Shrey Baid26912972020-04-16 21:02:31 +05302073 logger.Debugw("creating-entry-for-pending-flow-delete",
2074 log.Fields{
2075 "flow-id": flowID,
2076 "intf": Intf,
2077 "onu-id": onuID,
2078 "uni-id": uniID,
2079 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302080 f.pendingFlowDelete.Store(pnFlDelKey, 1)
2081 } else {
2082 pnFlDels := val.(int) + 1
Shrey Baid26912972020-04-16 21:02:31 +05302083 logger.Debugw("updating-flow-delete-entry",
2084 log.Fields{
2085 "flow-id": flowID,
2086 "intf": Intf,
2087 "onu-id": onuID,
2088 "uni-id": uniID,
2089 "currPendingFlowCnt": pnFlDels,
2090 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302091 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
2092 }
2093
2094 defer f.deletePendingFlows(Intf, onuID, uniID)
2095 }
2096
Shrey Baid26912972020-04-16 21:02:31 +05302097 logger.Debugw("releasing-flow-id-to-resource-manager",
2098 log.Fields{
2099 "Intf": Intf,
2100 "onu-id": onuID,
2101 "uni-id": uniID,
2102 "flow-id": flowID,
2103 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302104 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002105
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002106 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302107 tpPath := f.getTPpath(Intf, uni, tpID)
Shrey Baid26912972020-04-16 21:02:31 +05302108 logger.Debugw("getting-techprofile-instance-for-subscriber",
2109 log.Fields{
2110 "TP-PATH": tpPath,
2111 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302112 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00002113 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +05302114 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
2115 log.Fields{
2116 "tp-id": tpID,
2117 "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002118 }
2119
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302120 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00002121 if f.isGemPortUsedByAnotherFlow(gemPK) {
2122 flowIDs := f.flowsUsedByGemPort[gemPK]
2123 for i, flowIDinMap := range flowIDs {
2124 if flowIDinMap == flowID {
2125 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302126 // everytime flowsUsedByGemPort cache is updated the same should be updated
2127 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002128 f.flowsUsedByGemPort[gemPK] = flowIDs
npujarec5762e2020-01-01 14:08:48 +05302129 f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00002130 break
2131 }
2132 }
Shrey Baid26912972020-04-16 21:02:31 +05302133 logger.Debugw("gem-port-id-is-still-used-by-other-flows",
2134 log.Fields{
2135 "gemport-id": gemPortID,
2136 "usedByFlows": flowIDs,
2137 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302138 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00002139 }
Shrey Baid26912972020-04-16 21:02:31 +05302140 logger.Debugf("gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05302141 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002142 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
2143 // 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 +05302144 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Girish Gowdrac3037402020-01-22 20:29:53 +05302145 f.deleteGemPortFromLocalCache(Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002146 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302147 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
2148 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002149 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05302150 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
2151 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002152 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05302153 // Delete the gem port on the ONU.
2154 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302155 logger.Errorw("error-processing-delete-gem-port-towards-onu",
2156 log.Fields{
2157 "err": err,
2158 "intf": Intf,
2159 "onu-id": onuID,
2160 "uni-id": uniID,
2161 "device-id": f.deviceHandler.device.Id,
2162 "gemport-id": gemPortID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302163 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002164 switch techprofileInst := techprofileInst.(type) {
2165 case *tp.TechProfile:
2166 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
2167 if !ok {
2168 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
2169 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
2170 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
2171 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
2172 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
2173 // Delete the TCONT on the ONU.
2174 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
2175 logger.Errorw("error-processing-delete-tcont-towards-onu",
2176 log.Fields{
2177 "intf": Intf,
2178 "onu-id": onuID,
2179 "uni-id": uniID,
2180 "device-id": f.deviceHandler.device.Id,
2181 "alloc-id": techprofileInst.UsScheduler.AllocID})
2182 }
2183 }
2184 case *tp.EponProfile:
npujarec5762e2020-01-01 14:08:48 +05302185 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
npujarec5762e2020-01-01 14:08:48 +05302186 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002187 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302188 // Delete the TCONT on the ONU.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002189 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.AllocID), tpPath); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302190 logger.Errorw("error-processing-delete-tcont-towards-onu",
2191 log.Fields{
2192 "intf": Intf,
2193 "onu-id": onuID,
2194 "uni-id": uniID,
2195 "device-id": f.deviceHandler.device.Id,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002196 "alloc-id": techprofileInst.AllocID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302197 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002198 default:
2199 logger.Errorw("error-unknown-tech",
2200 log.Fields{
2201 "techprofileInst": techprofileInst})
Gamze Abakafee36392019-10-03 11:17:24 +00002202 }
2203 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002204 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302205 return nil
2206}
2207
David K. Bainbridge794735f2020-02-11 21:01:37 -08002208// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302209func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302210
Shrey Baid26912972020-04-16 21:02:31 +05302211 logger.Infow("clear-flow-from-resource-manager",
2212 log.Fields{
2213 "flowDirection": flowDirection,
2214 "flow": *flow,
2215 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002216
2217 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05302218 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002219 return
2220 }
2221
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302222 var updatedFlows []rsrcMgr.FlowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302223 classifierInfo := make(map[string]interface{})
2224
2225 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
2226 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002227 logger.Error(err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302228 return
2229 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302230
David K. Bainbridge794735f2020-02-11 21:01:37 -08002231 onuID := int32(onu)
2232 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302233
2234 for _, field := range flows.GetOfbFields(flow) {
2235 if field.Type == flows.IP_PROTO {
2236 classifierInfo[IPProto] = field.GetIpProto()
Shrey Baid26912972020-04-16 21:02:31 +05302237 logger.Debugw("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302238 }
2239 }
Shrey Baid26912972020-04-16 21:02:31 +05302240 logger.Infow("extracted-access-info-from-flow-to-be-deleted",
2241 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002242 "flow-id": flow.Id,
2243 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302244 "onu-id": onuID,
2245 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302246
2247 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2248 onuID = -1
2249 uniID = -1
Shrey Baid26912972020-04-16 21:02:31 +05302250 logger.Debug("trap-on-nni-flow-set-oni--uni-to- -1")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002251 Intf, err = IntfIDFromNniPortNum(inPort)
2252 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002253 logger.Errorw("invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002254 log.Fields{
2255 "port-number": inPort,
2256 "error": err})
2257 return
2258 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302259 }
npujarec5762e2020-01-01 14:08:48 +05302260 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002261 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302262 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302263 if flowInfo == nil {
Shrey Baid26912972020-04-16 21:02:31 +05302264 logger.Debugw("no-flowinfo-found-in-kv-store",
2265 log.Fields{
2266 "intf": Intf,
2267 "onu-id": onuID,
2268 "uni-id": uniID,
2269 "flow-id": flowID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302270 return
2271 }
2272 updatedFlows = nil
2273 for _, flow := range *flowInfo {
2274 updatedFlows = append(updatedFlows, flow)
2275 }
2276
2277 for i, storedFlow := range updatedFlows {
2278 if flow.Id == storedFlow.LogicalFlowID {
2279 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Shrey Baid26912972020-04-16 21:02:31 +05302280 logger.Debugw("flow-to-be-deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002281 // DKB
Matteo Scandolo92186242020-06-12 10:54:18 -07002282 if err = f.removeFlowFromDevice(&removeFlowMessage, flow.Id); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002283 logger.Errorw("failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002284 return
2285 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002286 logger.Info("flow-removed-from-device-successfully", log.Fields{
2287 "flow-id": flow.Id,
2288 "stored-flow": storedFlow,
2289 "device-id": f.deviceHandler.device.Id,
2290 "stored-flow-id": flowID,
2291 "onu-id": onuID,
2292 "intf": Intf,
2293 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08002294 //Remove the Flow from FlowInfo
2295 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
2296 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
2297 flowID, flowDirection, portNum, updatedFlows); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07002298 logger.Error("failed-to-clear-resources-for-flow", log.Fields{
2299 "flow-id": flow.Id,
2300 "stored-flow": storedFlow,
2301 "device-id": f.deviceHandler.device.Id,
2302 "stored-flow-id": flowID,
2303 "onu-id": onuID,
2304 "intf": Intf,
2305 })
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302306 return
2307 }
2308 }
2309 }
2310 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002311}
2312
Esin Karamanccb714b2019-11-29 15:02:06 +00002313//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
2314// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05302315func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002316 classifierInfo := make(map[string]interface{})
2317 formulateClassifierInfoFromFlow(classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00002318 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002319
2320 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302321 logger.Warnw("no-inport-found--cannot-release-resources-of-the-multicast-flow", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002322 return
2323 }
2324
Esin Karamanccb714b2019-11-29 15:02:06 +00002325 var onuID = int32(NoneOnuID)
2326 var uniID = int32(NoneUniID)
2327 var flowID uint32
2328 var updatedFlows []rsrcMgr.FlowInfo
2329
npujarec5762e2020-01-01 14:08:48 +05302330 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002331
2332 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302333 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002334 if flowInfo == nil {
Shrey Baid26912972020-04-16 21:02:31 +05302335 logger.Debugw("no-multicast-flowinfo-found-in-the-kv-store",
2336 log.Fields{
2337 "intf": networkInterfaceID,
2338 "onu-id": onuID,
2339 "uni-id": uniID,
2340 "flow-id": flowID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002341 continue
2342 }
2343 updatedFlows = nil
2344 for _, flow := range *flowInfo {
2345 updatedFlows = append(updatedFlows, flow)
2346 }
2347 for i, storedFlow := range updatedFlows {
2348 if flow.Id == storedFlow.LogicalFlowID {
2349 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Shrey Baid26912972020-04-16 21:02:31 +05302350 logger.Debugw("multicast-flow-to-be-deleted",
2351 log.Fields{
2352 "flow": storedFlow,
2353 "flow-id": flow.Id,
2354 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002355 //remove from device
Matteo Scandolo92186242020-06-12 10:54:18 -07002356 if err := f.removeFlowFromDevice(&removeFlowMessage, flow.Id); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002357 // DKB
Girish Kumar2ad402b2020-03-20 19:45:12 +00002358 logger.Errorw("failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002359 log.Fields{
2360 "flow-id": flow.Id,
2361 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002362 return
2363 }
Shrey Baid26912972020-04-16 21:02:31 +05302364 logger.Infow("multicast-flow-removed-from-device-successfully", log.Fields{"flow-id": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002365 //Remove the Flow from FlowInfo
2366 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05302367 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302368 logger.Errorw("failed-to-delete-multicast-flow-from-the-kv-store",
2369 log.Fields{"flow": storedFlow,
2370 "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002371 return
2372 }
2373 //release flow id
Shrey Baid26912972020-04-16 21:02:31 +05302374 logger.Debugw("releasing-multicast-flow-id",
2375 log.Fields{"flow-id": flowID,
2376 "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05302377 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002378 }
2379 }
2380 }
2381}
2382
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002383//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002384func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002385 logger.Infow("removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302386 var direction string
2387 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002388
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302389 for _, action := range flows.GetActions(flow) {
2390 if action.Type == flows.OUTPUT {
2391 if out := action.GetOutput(); out != nil {
2392 actionInfo[Output] = out.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002393 logger.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302394 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302395 logger.Error("invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002396 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002397 }
2398 }
2399 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002400
2401 if flows.HasGroup(flow) {
2402 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07002403 f.clearFlowFromResourceManager(ctx, flow, direction)
2404 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002405 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302406 direction = Upstream
2407 } else {
2408 direction = Downstream
2409 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302410
Girish Gowdracefae192020-03-19 18:14:10 -07002411 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(flow, direction)
2412 if err != nil {
2413 return err
2414 }
2415
2416 userKey := tpLockKey{intfID, onuID, uniID}
2417
2418 // Serialize flow removes on a per subscriber basis
2419 if f.perUserFlowHandleLock.TryLock(userKey) {
2420 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
2421 f.perUserFlowHandleLock.Unlock(userKey)
2422 } else {
2423 // Ideally this should never happen
Shrey Baid26912972020-04-16 21:02:31 +05302424 logger.Errorw("failed-to-acquire-lock-to-remove-flow--remove-aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07002425 return errors.New("failed-to-acquire-per-user-lock")
2426 }
2427
2428 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002429}
2430
Girish Gowdra3d633032019-12-10 16:37:05 +05302431func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
2432 uniID uint32, ch chan bool) {
2433 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2434 for {
2435 select {
2436 case <-time.After(20 * time.Millisecond):
2437 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Shrey Baid26912972020-04-16 21:02:31 +05302438 logger.Debug("pending-flow-deletes-completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05302439 ch <- true
2440 return
2441 }
2442 case <-ctx.Done():
Shrey Baid26912972020-04-16 21:02:31 +05302443 logger.Error("flow-delete-wait-handler-routine-canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05302444 return
2445 }
2446 }
2447}
2448
Esin Karamanae41e2b2019-12-17 18:13:13 +00002449//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2450func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2451 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2452 if ethType, ok := classifierInfo[EthType]; ok {
2453 if ethType.(uint32) == IPv4EthType {
2454 if ipProto, ok := classifierInfo[IPProto]; ok {
2455 if ipProto.(uint32) == IgmpProto {
2456 return true
2457 }
2458 }
2459 }
2460 }
2461 }
2462 return false
2463}
2464
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002465// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302466// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002467func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002468 classifierInfo := make(map[string]interface{})
2469 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002470 var UsMeterID uint32
2471 var DsMeterID uint32
2472
Shrey Baid26912972020-04-16 21:02:31 +05302473 logger.Infow("adding-flow",
2474 log.Fields{
2475 "flow": flow,
2476 "flowmetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002477 formulateClassifierInfoFromFlow(classifierInfo, flow)
2478
2479 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
2480 if err != nil {
2481 // Error logging is already done in the called function
2482 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002483 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302484 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002485
Esin Karamanccb714b2019-11-29 15:02:06 +00002486 if flows.HasGroup(flow) {
2487 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002488 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002489 }
2490
manikkaraj k17652a72019-05-06 09:06:36 -04002491 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00002492 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
2493 if err != nil {
2494 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002495 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002496 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002497
Shrey Baid26912972020-04-16 21:02:31 +05302498 logger.Debugw("flow-ports",
2499 log.Fields{
2500 "classifierinfo_inport": classifierInfo[InPort],
2501 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002502 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002503
Humera Kouser94d7a842019-08-25 19:04:32 -04002504 if ethType, ok := classifierInfo[EthType]; ok {
2505 if ethType.(uint32) == LldpEthType {
Shrey Baid26912972020-04-16 21:02:31 +05302506 logger.Info("adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002507 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002508 }
2509 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002510 if ipProto, ok := classifierInfo[IPProto]; ok {
2511 if ipProto.(uint32) == IPProtoDhcp {
2512 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302513 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002514 logger.Debug("trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002515 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002516 }
2517 }
2518 }
2519 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002520 if isIgmpTrapDownstreamFlow(classifierInfo) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002521 logger.Debug("trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002522 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002523 }
A R Karthick1f85b802019-10-11 05:06:05 +00002524
2525 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
npujarec5762e2020-01-01 14:08:48 +05302526 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002527
Chaitrashree G S90a17952019-11-14 21:51:21 -05002528 TpID, err := getTpIDFromFlow(flow)
2529 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302530 return olterrors.NewErrNotFound("tpid-for-flow",
2531 log.Fields{
2532 "flow": flow,
2533 "intf-id": IntfID,
2534 "onu-id": onuID,
2535 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002536 }
Shrey Baid26912972020-04-16 21:02:31 +05302537 logger.Debugw("tpid-for-this-subcriber",
2538 log.Fields{
2539 "tp-id": TpID,
2540 "intf-id": intfID,
2541 "onu-id": onuID,
2542 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002543 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002544 UsMeterID = flows.GetMeterIdFromFlow(flow)
Shrey Baid26912972020-04-16 21:02:31 +05302545 logger.Debugw("upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002546 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002547 DsMeterID = flows.GetMeterIdFromFlow(flow)
Shrey Baid26912972020-04-16 21:02:31 +05302548 logger.Debugw("downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002549
2550 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302551
2552 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2553 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Shrey Baid26912972020-04-16 21:02:31 +05302554 logger.Debugw("no-pending-flows-found--going-ahead-with-flow-install",
2555 log.Fields{
2556 "intf-id": intfID,
2557 "onu-id": onuID,
2558 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302559 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302560 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05302561 pendingFlowDelComplete := make(chan bool)
2562 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
2563 select {
2564 case <-pendingFlowDelComplete:
Shrey Baid26912972020-04-16 21:02:31 +05302565 logger.Debugw("all-pending-flow-deletes-completed",
2566 log.Fields{
2567 "intf-id": intfID,
2568 "onu-id": onuID,
2569 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302570 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302571
2572 case <-time.After(10 * time.Second):
Shrey Baid26912972020-04-16 21:02:31 +05302573 return olterrors.NewErrTimeout("pending-flow-deletes",
2574 log.Fields{
2575 "intf-id": intfID,
2576 "onu-id": onuID,
2577 "uni-id": uniID}, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +05302578 }
2579 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002580 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002581}
2582
Esin Karamanccb714b2019-11-29 15:02:06 +00002583// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002584func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002585 classifierInfo[PacketTagType] = DoubleTag
Shrey Baid26912972020-04-16 21:02:31 +05302586 logger.Debugw("add-multicast-flow", log.Fields{
2587 "classifier-info": classifierInfo,
2588 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002589
Esin Karaman65409d82020-03-18 10:58:18 +00002590 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002591 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002592 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002593 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002594 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
2595 //otherwise, classification is based on ipv4_dst by default.
2596 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
2597 mcastFlowClassificationByEthDst := false
2598
2599 if mcastFlowClassificationByEthDst {
2600 //replace ipDst with ethDst
2601 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
2602 flows.IsMulticastIp(ipv4Dst.(uint32)) {
2603 // replace ipv4_dst classifier with eth_dst
2604 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
2605 delete(classifierInfo, Ipv4Dst)
2606 classifierInfo[EthDst] = multicastMac
Shrey Baid26912972020-04-16 21:02:31 +05302607 logger.Debugw("multicast-ip-to-mac-conversion-success",
2608 log.Fields{
2609 "ip:": ipv4Dst.(uint32),
2610 "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002611 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002612 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002613 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002614
David K. Bainbridge794735f2020-02-11 21:01:37 -08002615 onuID := NoneOnuID
2616 uniID := NoneUniID
2617 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00002618
David K. Bainbridge794735f2020-02-11 21:01:37 -08002619 flowStoreCookie := getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302620 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05302621 logger.Infow("multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002622 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002623 }
npujarec5762e2020-01-01 14:08:48 +05302624 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00002625 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302626 return olterrors.NewErrNotFound("multicast-flow-id",
2627 log.Fields{
2628 "interface-id": networkInterfaceID,
2629 "onu-id": onuID,
2630 "uni-id": uniID,
2631 "gem-port-id": gemPortID,
2632 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002633 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002634 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002635 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2636 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002637 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002638 }
2639 groupID := actionInfo[GroupID].(uint32)
2640 multicastFlow := openoltpb2.Flow{
2641 FlowId: flowID,
2642 FlowType: Multicast,
2643 NetworkIntfId: int32(networkInterfaceID),
2644 GroupId: groupID,
2645 Classifier: classifierProto,
2646 Priority: int32(flow.Priority),
2647 Cookie: flow.Cookie}
2648
David K. Bainbridge794735f2020-02-11 21:01:37 -08002649 if err = f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002650 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002651 }
Shrey Baid26912972020-04-16 21:02:31 +05302652 logger.Info("multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002653 //get cached group
2654 group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true)
2655 if err == nil {
2656 //calling groupAdd to set group members after multicast flow creation
Andrea Campanellac63bba92020-03-10 17:01:04 +01002657 if err = f.ModifyGroup(ctx, group); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002658 //cached group can be removed now
2659 f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002660 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002661 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002662 }
2663 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002664
2665 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2666 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2667 int32(onuID),
2668 int32(uniID),
2669 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002670 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002671 }
2672 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002673}
2674
Esin Karaman65409d82020-03-18 10:58:18 +00002675//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2676func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2677 if inPort, ok := classifierInfo[InPort]; ok {
2678 nniInterfaceID, err := IntfIDFromNniPortNum(inPort.(uint32))
2679 if err != nil {
2680 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2681 }
2682 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002683 }
Esin Karaman65409d82020-03-18 10:58:18 +00002684 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302685 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002686 if e == nil && len(nniPorts) > 0 {
2687 return nniPorts[0], nil
2688 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302689 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002690}
2691
2692// AddGroup add or update the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002693func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002694 logger.Infow("add-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002695 if group == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002696 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002697 }
2698
2699 groupToOlt := openoltpb2.Group{
2700 GroupId: group.Desc.GroupId,
2701 Command: openoltpb2.Group_SET_MEMBERS,
2702 Action: f.buildGroupAction(),
2703 }
2704
Shrey Baid26912972020-04-16 21:02:31 +05302705 logger.Debugw("sending-group-to-device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05302706 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002707 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002708 return olterrors.NewErrAdapter("add-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002709 }
2710 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05302711 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002712 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002713 }
Shrey Baid26912972020-04-16 21:02:31 +05302714 logger.Infow("add-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002715 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002716}
2717
2718//buildGroupAction creates and returns a group action
2719func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2720 var actionCmd openoltpb2.ActionCmd
2721 var action openoltpb2.Action
2722 action.Cmd = &actionCmd
2723 //pop outer vlan
2724 action.Cmd.RemoveOuterTag = true
2725 return &action
2726}
2727
2728// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002729func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002730 logger.Infow("modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002731 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002732 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002733 }
2734
Andrea Campanellac63bba92020-03-10 17:01:04 +01002735 newGroup := f.buildGroup(group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002736 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302737 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002738
2739 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002740 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002741 }
2742
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002743 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002744 if groupExists {
2745 // group already exists
2746 current = f.buildGroup(group.Desc.GroupId, val.Desc.GetBuckets())
Shrey Baid26912972020-04-16 21:02:31 +05302747 logger.Debugw("modify-group--group exists",
2748 log.Fields{
2749 "group on the device": val,
2750 "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002751 } else {
2752 current = f.buildGroup(group.Desc.GroupId, nil)
2753 }
2754
Shrey Baid26912972020-04-16 21:02:31 +05302755 logger.Debugw("modify-group--comparing-current-and-new",
2756 log.Fields{
2757 "group on the device": current,
2758 "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002759 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002760 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002761 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002762 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002763
Shrey Baid26912972020-04-16 21:02:31 +05302764 logger.Infow("modify-group--differences found", log.Fields{
2765 "membersToBeAdded": membersToBeAdded,
2766 "membersToBeRemoved": membersToBeRemoved,
2767 "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002768
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002769 groupToOlt := openoltpb2.Group{
2770 GroupId: group.Desc.GroupId,
2771 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002772 var errAdd, errRemoved error
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002773 if membersToBeAdded != nil && len(membersToBeAdded) > 0 {
2774 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2775 groupToOlt.Members = membersToBeAdded
2776 //execute addMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002777 errAdd = f.callGroupAddRemove(&groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002778 }
2779 if membersToBeRemoved != nil && len(membersToBeRemoved) > 0 {
2780 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2781 groupToOlt.Members = membersToBeRemoved
2782 //execute removeMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002783 errRemoved = f.callGroupAddRemove(&groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002784 }
2785
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002786 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002787 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302788 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002789 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002790 }
Shrey Baid26912972020-04-16 21:02:31 +05302791 logger.Infow("modify-group-was-success--storing-group",
2792 log.Fields{
2793 "group": group,
2794 "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002795 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302796 logger.Warnw("one-of-the-group-add/remove-operations-failed--cannot-save-group-modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002797 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002798 if errAdd != nil {
2799 return errAdd
2800 }
2801 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002802 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002803 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002804}
2805
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002806//callGroupAddRemove performs add/remove buckets operation for the indicated group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002807func (f *OpenOltFlowMgr) callGroupAddRemove(group *openoltpb2.Group) error {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002808 if err := f.performGroupOperation(group); err != nil {
2809 st, _ := status.FromError(err)
2810 //ignore already exists error code
2811 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002812 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002813 }
2814 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002815 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002816}
2817
2818//findDiff compares group members and finds members which only exists in groups2
2819func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2820 var members []*openoltpb2.GroupMember
2821 for _, bucket := range group2.Members {
2822 if !f.contains(group1.Members, bucket) {
2823 // bucket does not exist and must be added
2824 members = append(members, bucket)
2825 }
2826 }
2827 return members
2828}
2829
2830//contains returns true if the members list contains the given member; false otherwise
2831func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2832 for _, groupMember := range members {
2833 if groupMember.InterfaceId == member.InterfaceId {
2834 return true
2835 }
2836 }
2837 return false
2838}
2839
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002840//performGroupOperation call performGroupOperation operation of openolt proto
2841func (f *OpenOltFlowMgr) performGroupOperation(group *openoltpb2.Group) error {
Shrey Baid26912972020-04-16 21:02:31 +05302842 logger.Debugw("sending-group-to-device",
2843 log.Fields{
2844 "groupToOlt": group,
2845 "command": group.Command})
Esin Karamanccb714b2019-11-29 15:02:06 +00002846 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2847 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002848 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002849 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002850 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002851}
2852
2853//buildGroup build openoltpb2.Group from given group id and bucket list
2854func (f *OpenOltFlowMgr) buildGroup(groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
2855 group := openoltpb2.Group{
2856 GroupId: groupID}
2857 // create members of the group
2858 if buckets != nil {
2859 for _, ofBucket := range buckets {
2860 member := f.buildMember(ofBucket)
2861 if member != nil && !f.contains(group.Members, member) {
2862 group.Members = append(group.Members, member)
2863 }
2864 }
2865 }
2866 return &group
2867}
2868
2869//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
2870func (f *OpenOltFlowMgr) buildMember(ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
2871 var outPort uint32
2872 outPortFound := false
2873 for _, ofAction := range ofBucket.Actions {
2874 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2875 outPort = ofAction.GetOutput().Port
2876 outPortFound = true
2877 }
2878 }
2879
2880 if !outPortFound {
Shrey Baid26912972020-04-16 21:02:31 +05302881 logger.Debugw("bucket-skipped-since-no-out-port-found-in-it", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002882 return nil
2883 }
2884 interfaceID := IntfIDFromUniPortNum(outPort)
Shrey Baid26912972020-04-16 21:02:31 +05302885 logger.Debugw("got-associated-interface-id-of-the-port",
2886 log.Fields{
2887 "portNumber:": outPort,
2888 "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002889 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2890 member := openoltpb2.GroupMember{
2891 InterfaceId: interfaceID,
2892 InterfaceType: openoltpb2.GroupMember_PON,
2893 GemPortId: groupInfo.gemPortID,
2894 Priority: groupInfo.servicePriority,
2895 }
2896 //add member to the group
2897 return &member
2898 }
Shrey Baid26912972020-04-16 21:02:31 +05302899 logger.Warnf("bucket-skipped-since-interface-2-gem-mapping-cannot-be-found", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002900 return nil
2901}
2902
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002903//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04002904func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002905
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002906 onuDev, err := f.getOnuDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302907 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302908 logger.Errorw("couldnt-find-onu-child-device",
2909 log.Fields{
2910 "intf-id": intfID,
2911 "onu-id": onuID,
2912 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002913 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302914 }
Shrey Baid26912972020-04-16 21:02:31 +05302915 logger.Debugw("got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002916
Manikkaraj kb1d51442019-07-23 10:41:02 -04002917 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002918 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Matteo Scandolo92186242020-06-12 10:54:18 -07002919 logger.Debugw("sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
manikkaraj k17652a72019-05-06 09:06:36 -04002920 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2921 tpDownloadMsg,
2922 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302923 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002924 onuDev.deviceType,
2925 onuDev.deviceID,
2926 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002927 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302928 return olterrors.NewErrCommunication("send-techprofile-download-request",
2929 log.Fields{
2930 "from-adapter": f.deviceHandler.device.Type,
2931 "to-adapter": onuDev.deviceType,
2932 "onu-id": onuDev.deviceID,
2933 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002934 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002935 logger.Infow("success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302936 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302937}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002938
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302939//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002940func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302941
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002942 f.onuGemInfoLock[intfID].Lock()
2943 defer f.onuGemInfoLock[intfID].Unlock()
2944
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302945 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2946 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002947 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002948 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302949 }
Shrey Baid26912972020-04-16 21:02:31 +05302950 logger.Infow("updated-onuinfo",
2951 log.Fields{
2952 "intf-id": intfID,
2953 "onu-id": onuID,
2954 "serial-num": serialNum,
2955 "onu": onu,
2956 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002957 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002958}
2959
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302960//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302961func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002962
2963 f.onuGemInfoLock[intfID].Lock()
2964 defer f.onuGemInfoLock[intfID].Unlock()
2965
Shrey Baid26912972020-04-16 21:02:31 +05302966 logger.Infow("adding-gem-to-onu-info-map",
2967 log.Fields{
2968 "gem": gemPort,
2969 "intf": intfID,
2970 "onu": onuID,
2971 "device-id": f.deviceHandler.device.Id,
2972 "onu-gem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302973 onugem := f.onuGemInfo[intfID]
2974 // update the gem to the local cache as well as to kv strore
2975 for idx, onu := range onugem {
2976 if onu.OnuID == onuID {
2977 // check if gem already exists , else update the cache and kvstore
2978 for _, gem := range onu.GemPorts {
2979 if gem == gemPort {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002980 logger.Debugw("gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302981 log.Fields{
2982 "gem": gemPort,
2983 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302984 return
2985 }
2986 }
2987 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2988 f.onuGemInfo[intfID] = onugem
2989 }
2990 }
npujarec5762e2020-01-01 14:08:48 +05302991 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302992 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302993 logger.Errorw("failed-to-add-gem-to-onu",
2994 log.Fields{
2995 "intf-id": intfID,
2996 "onu-id": onuID,
2997 "gemPort": gemPort,
2998 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002999 return
3000 }
Shrey Baid26912972020-04-16 21:02:31 +05303001 logger.Infow("gem-added-to-onu-info-map",
3002 log.Fields{
3003 "gem": gemPort,
3004 "intf": intfID,
3005 "onu": onuID,
3006 "device-id": f.deviceHandler.device.Id,
3007 "onu-gem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003008}
3009
3010// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003011
3012//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003013func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303014
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003015 f.onuGemInfoLock[intfID].Lock()
3016 defer f.onuGemInfoLock[intfID].Unlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303017
Shrey Baid26912972020-04-16 21:02:31 +05303018 logger.Infow("getting-onu-id-from-gem-port-and-pon-port",
3019 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003020 "device-id": f.deviceHandler.device.Id,
3021 "onu-geminfo": f.onuGemInfo[intfID],
3022 "intf-id": intfID,
3023 "gemport-id": gemPortID})
Matteo Scandolod625b4c2020-04-02 16:16:01 -07003024
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303025 // get onuid from the onugem info cache
3026 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07003027
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303028 for _, onu := range onugem {
3029 for _, gem := range onu.GemPorts {
3030 if gem == gemPortID {
3031 return onu.OnuID, nil
3032 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003033 }
3034 }
Thomas Lee S94109f12020-03-03 16:39:29 +05303035 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003036 "interface-id": intfID,
3037 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00003038 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003039}
3040
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003041//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05303042func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003043 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003044 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003045 var err error
3046
3047 if packetIn.IntfType == "pon" {
3048 // packet indication does not have serial number , so sending as nil
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003049 if onuID, err = f.getOnuIDfromGemPortMap(packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003050 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003051 return logicalPortNum, err
3052 }
3053 if packetIn.PortNo != 0 {
3054 logicalPortNum = packetIn.PortNo
3055 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003056 uniID := uint32(0) // FIXME - multi-uni support
3057 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003058 }
3059 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
npujarec5762e2020-01-01 14:08:48 +05303060 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003061 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003062 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003063 }
Shrey Baid26912972020-04-16 21:02:31 +05303064 logger.Infow("retrieved-logicalport-from-packet-in",
3065 log.Fields{
3066 "logical-port-num": logicalPortNum,
3067 "intf-type": packetIn.IntfType,
3068 "packet": hex.EncodeToString(packetIn.Pkt),
3069 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003070 return logicalPortNum, nil
3071}
3072
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003073//GetPacketOutGemPortID returns gemPortId
npujarec5762e2020-01-01 14:08:48 +05303074func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003075 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003076 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303077
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003078 f.onuGemInfoLock[intfID].Lock()
3079 defer f.onuGemInfoLock[intfID].Unlock()
3080
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303081 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
3082
3083 gemPortID, ok := f.packetInGemPort[pktInkey]
3084 if ok {
Shrey Baid26912972020-04-16 21:02:31 +05303085 logger.Debugw("found-gemport-for-pktin-key",
3086 log.Fields{
3087 "pktinkey": pktInkey,
3088 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303089 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003090 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303091 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
npujarec5762e2020-01-01 14:08:48 +05303092 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303093 if err == nil {
3094 if gemPortID != 0 {
3095 f.packetInGemPort[pktInkey] = gemPortID
Shrey Baid26912972020-04-16 21:02:31 +05303096 logger.Infow("found-gem-port-from-kv-store-and-updating-cache-with-gemport",
3097 log.Fields{
3098 "pktinkey": pktInkey,
3099 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303100 return gemPortID, nil
3101 }
3102 }
Shrey Baid26912972020-04-16 21:02:31 +05303103 return uint32(0), olterrors.NewErrNotFound("gem-port",
3104 log.Fields{
3105 "pktinkey": pktInkey,
3106 "gem": gemPortID}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003107}
3108
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003109// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303110func installFlowOnAllGemports(ctx context.Context,
3111 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003112 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003113 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05303114 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303115 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303116 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003117 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003118 args map[string]uint32,
3119 classifier map[string]interface{}, action map[string]interface{},
3120 logicalFlow *ofp.OfpFlowStats,
3121 gemPorts []uint32,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003122 TpInst interface{},
Manikkaraj kb1d51442019-07-23 10:41:02 -04003123 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00003124 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003125 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003126 vlanID ...uint32) {
Shrey Baid26912972020-04-16 21:02:31 +05303127 logger.Debugw("installing-flow-on-all-gem-ports",
3128 log.Fields{
3129 "FlowType": FlowType,
3130 "gemPorts": gemPorts,
3131 "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05303132
Gamze Abaka724d0852020-03-18 12:10:24 +00003133 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
3134 // We need to trim prefix "0b", before further processing
3135 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
3136 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
3137
3138 // If a particular character in the string is set to '1', identify the index of this character from
3139 // the LSB position which marks the PCP bit consumed by the given gem port.
3140 // This PCP bit now becomes a classifier in the flow.
3141
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003142 switch TpInst := TpInst.(type) {
3143 case *tp.TechProfile:
3144 attributes := TpInst.DownstreamGemPortAttributeList
3145 if direction == Upstream {
3146 attributes = TpInst.UpstreamGemPortAttributeList
Gamze Abaka724d0852020-03-18 12:10:24 +00003147 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003148
3149 for _, gemPortAttribute := range attributes {
3150 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
3151 continue
Gamze Abaka724d0852020-03-18 12:10:24 +00003152 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003153 gemPortID := gemPortAttribute.GemportID
3154 if allPbitsMarked(gemPortAttribute.PbitMap) {
3155 classifier[VlanPcp] = uint32(VlanPCPMask)
3156 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3157 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3158 } else if FlowType == EapolFlow {
3159 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3160 }
3161 } else {
3162 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
3163 if pbitSet == BinaryBit1 {
3164 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3165 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3166 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3167 } else if FlowType == EapolFlow {
3168 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3169 }
3170 }
3171 }
3172 }
3173 }
3174 case *tp.EponProfile:
3175 if direction == Upstream {
3176 attributes := TpInst.UpstreamQueueAttributeList
3177 for _, queueAttribute := range attributes {
3178 gemPortID := queueAttribute.GemportID
3179 if allPbitsMarked(queueAttribute.PbitMap) {
3180 classifier[VlanPcp] = uint32(VlanPCPMask)
Gamze Abaka724d0852020-03-18 12:10:24 +00003181 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003182 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003183 } else if FlowType == EapolFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003184 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003185 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003186 } else {
3187 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3188 if pbitSet == BinaryBit1 {
3189 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3190 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3191 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3192 } else if FlowType == EapolFlow {
3193 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3194 }
3195 }
3196 }
3197 }
3198 }
3199 } else {
3200 attributes := TpInst.DownstreamQueueAttributeList
3201 for _, queueAttribute := range attributes {
3202 gemPortID := queueAttribute.GemportID
3203 if allPbitsMarked(queueAttribute.PbitMap) {
3204 classifier[VlanPcp] = uint32(VlanPCPMask)
3205 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3206 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3207 } else if FlowType == EapolFlow {
3208 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3209 }
3210 } else {
3211 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3212 if pbitSet == BinaryBit1 {
3213 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3214 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3215 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3216 } else if FlowType == EapolFlow {
3217 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3218 }
3219 }
3220 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05303221 }
3222 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04003223 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003224 default:
3225 logger.Errorw("unknown-tech", log.Fields{"tpInst": TpInst})
Manikkaraj kb1d51442019-07-23 10:41:02 -04003226 }
3227}
3228
Gamze Abaka724d0852020-03-18 12:10:24 +00003229func allPbitsMarked(pbitMap string) bool {
3230 for pos, pBit := range pbitMap {
3231 if pos >= 2 && pBit != BinaryBit1 {
3232 return false
3233 }
3234 }
3235 return true
3236}
3237
David K. Bainbridge794735f2020-02-11 21:01:37 -08003238func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05303239 logger.Debug("adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003240 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003241 classifier[PacketTagType] = DoubleTag
3242 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003243 /* We manage flowId resource pool on per PON port basis.
3244 Since this situation is tricky, as a hack, we pass the NNI port
3245 index (network_intf_id) as PON port Index for the flowId resource
3246 pool. Also, there is no ONU Id available for trapping DHCP packets
3247 on NNI port, use onu_id as -1 (invalid)
3248 ****************** CAVEAT *******************
3249 This logic works if the NNI Port Id falls within the same valid
3250 range of PON Port Ids. If this doesn't work for some OLT Vendor
3251 we need to have a re-look at this.
3252 *********************************************
3253 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003254 onuID := -1
3255 uniID := -1
3256 gemPortID := -1
3257 allocID := -1
David K. Bainbridge794735f2020-02-11 21:01:37 -08003258 networkInterfaceID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303259 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303260 return olterrors.NewErrNotFound("nni-intreface-id",
3261 log.Fields{
3262 "classifier": classifier,
3263 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003264 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303265 }
3266
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003267 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303268 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05303269 logger.Info("flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003270 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003271 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003272 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003273 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303274 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id",
3275 log.Fields{
3276 "interface-id": networkInterfaceID,
3277 "onu-id": onuID,
3278 "uni-id": uniID,
3279 "gem-port-id": gemPortID,
3280 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003281 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003282 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003283 classifierProto, err := makeOpenOltClassifierField(classifier)
3284 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003285 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003286 }
Shrey Baid26912972020-04-16 21:02:31 +05303287 logger.Debugw("created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003288 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003289 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003290 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003291 }
Shrey Baid26912972020-04-16 21:02:31 +05303292 logger.Debugw("created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003293 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3294 OnuId: int32(onuID), // OnuId not required
3295 UniId: int32(uniID), // UniId not used
3296 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07003297 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003298 AllocId: int32(allocID), // AllocId not used
3299 NetworkIntfId: int32(networkInterfaceID),
3300 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003301 Classifier: classifierProto,
3302 Action: actionProto,
3303 Priority: int32(logicalFlow.Priority),
3304 Cookie: logicalFlow.Cookie,
3305 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003306 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003307 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003308 }
Shrey Baid26912972020-04-16 21:02:31 +05303309 logger.Info("dhcp-trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003310 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3311 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3312 int32(onuID),
3313 int32(uniID),
3314 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003315 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003316 }
3317 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003318}
salmansiddiqui7ac62132019-08-22 03:58:50 +00003319
Esin Karamanae41e2b2019-12-17 18:13:13 +00003320//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
3321func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
3322 var packetType string
3323 ovid, ivid := false, false
3324 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
3325 vid := vlanID & VlanvIDMask
3326 if vid != ReservedVlan {
3327 ovid = true
3328 }
3329 }
3330 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
3331 vid := uint32(metadata)
3332 if vid != ReservedVlan {
3333 ivid = true
3334 }
3335 }
3336 if ovid && ivid {
3337 packetType = DoubleTag
3338 } else if !ovid && !ivid {
3339 packetType = Untagged
3340 } else {
3341 packetType = SingleTag
3342 }
3343 return packetType
3344}
3345
3346//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08003347func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05303348 logger.Infow("adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003349 action := make(map[string]interface{})
3350 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
3351 action[TrapToHost] = true
3352 /* We manage flowId resource pool on per PON port basis.
3353 Since this situation is tricky, as a hack, we pass the NNI port
3354 index (network_intf_id) as PON port Index for the flowId resource
3355 pool. Also, there is no ONU Id available for trapping packets
3356 on NNI port, use onu_id as -1 (invalid)
3357 ****************** CAVEAT *******************
3358 This logic works if the NNI Port Id falls within the same valid
3359 range of PON Port Ids. If this doesn't work for some OLT Vendor
3360 we need to have a re-look at this.
3361 *********************************************
3362 */
3363 onuID := -1
3364 uniID := -1
3365 gemPortID := -1
3366 allocID := -1
3367 networkInterfaceID, err := getNniIntfID(classifier, action)
3368 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303369 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003370 "classifier": classifier,
3371 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003372 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003373 }
3374 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303375 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05303376 logger.Info("igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003377 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003378 }
npujarec5762e2020-01-01 14:08:48 +05303379 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003380 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303381 return olterrors.NewErrNotFound("igmp-flow-id",
3382 log.Fields{
3383 "interface-id": networkInterfaceID,
3384 "onu-id": onuID,
3385 "uni-id": uniID,
3386 "gem-port-id": gemPortID,
3387 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003388 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003389 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003390 classifierProto, err := makeOpenOltClassifierField(classifier)
3391 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003392 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003393 }
Shrey Baid26912972020-04-16 21:02:31 +05303394 logger.Debugw("created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003395 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003396 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003397 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003398 }
Shrey Baid26912972020-04-16 21:02:31 +05303399 logger.Debugw("created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003400 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3401 OnuId: int32(onuID), // OnuId not required
3402 UniId: int32(uniID), // UniId not used
3403 FlowId: flowID,
3404 FlowType: Downstream,
3405 AllocId: int32(allocID), // AllocId not used
3406 NetworkIntfId: int32(networkInterfaceID),
3407 GemportId: int32(gemPortID), // GemportId not used
3408 Classifier: classifierProto,
3409 Action: actionProto,
3410 Priority: int32(logicalFlow.Priority),
3411 Cookie: logicalFlow.Cookie,
3412 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003413 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003414 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003415 }
Shrey Baid26912972020-04-16 21:02:31 +05303416 logger.Info("igmp-trap-on-nni-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003417 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3418 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3419 int32(onuID),
3420 int32(uniID),
3421 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003422 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003423 }
3424 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003425}
3426
salmansiddiqui7ac62132019-08-22 03:58:50 +00003427func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
3428 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05303429 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003430 }
3431 if Dir == tp_pb.Direction_UPSTREAM {
3432 return "upstream", nil
3433 } else if Dir == tp_pb.Direction_DOWNSTREAM {
3434 return "downstream", nil
3435 }
3436 return "", nil
3437}
3438
npujarec5762e2020-01-01 14:08:48 +05303439func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003440 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003441 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00003442 var gemPort uint32
3443 intfID := args[IntfID]
3444 onuID := args[OnuID]
3445 uniID := args[UniID]
3446 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003447 allocID := args[AllocID]
salmansiddiqui7ac62132019-08-22 03:58:50 +00003448 if ipProto, ok := classifierInfo[IPProto]; ok {
3449 if ipProto.(uint32) == IPProtoDhcp {
Matteo Scandolo92186242020-06-12 10:54:18 -07003450 logger.Infow("adding-dhcp-flow", log.Fields{
3451 "tp-id": tpID,
3452 "alloc-id": allocID,
3453 "intf-id": intfID,
3454 "onu-id": onuID,
3455 "uni-id": uniID,
3456 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003457 if pcp, ok := classifierInfo[VlanPcp]; ok {
3458 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3459 tp_pb.Direction_UPSTREAM,
3460 pcp.(uint32))
3461 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00003462
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003463 f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003464 } else {
3465 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003466 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003467 }
3468
Girish Gowdra32625212020-04-29 11:26:35 -07003469 } else if ipProto.(uint32) == IgmpProto {
Shrey Baid26912972020-04-16 21:02:31 +05303470 logger.Infow("adding-us-igmp-flow",
3471 log.Fields{
3472 "intf-id": intfID,
3473 "onu-id": onuID,
3474 "uni-id": uniID,
3475 "classifier-info:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003476 if pcp, ok := classifierInfo[VlanPcp]; ok {
3477 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3478 tp_pb.Direction_UPSTREAM,
3479 pcp.(uint32))
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003480 f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003481 } else {
3482 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003483 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003484 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003485 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303486 logger.Errorw("invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003487 return
3488 }
3489 } else if ethType, ok := classifierInfo[EthType]; ok {
3490 if ethType.(uint32) == EapEthType {
Matteo Scandolo92186242020-06-12 10:54:18 -07003491 logger.Infow("adding-eapol-flow", log.Fields{
3492 "intf-id": intfID,
3493 "onu-id": onuID,
3494 "uni-id": uniID,
3495 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003496 var vlanID uint32
3497 if val, ok := classifierInfo[VlanVid]; ok {
3498 vlanID = (val.(uint32)) & VlanvIDMask
3499 } else {
3500 vlanID = DefaultMgmtVlan
3501 }
3502 if pcp, ok := classifierInfo[VlanPcp]; ok {
3503 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3504 tp_pb.Direction_UPSTREAM,
3505 pcp.(uint32))
3506
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003507 f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003508 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003509 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003510 }
3511 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003512 } else if _, ok := actionInfo[PushVlan]; ok {
Matteo Scandolo92186242020-06-12 10:54:18 -07003513 logger.Infow("adding-upstream-data-rule", log.Fields{
3514 "intf-id": intfID,
3515 "onu-id": onuID,
3516 "uni-id": uniID,
3517 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003518 if pcp, ok := classifierInfo[VlanPcp]; ok {
3519 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3520 tp_pb.Direction_UPSTREAM,
3521 pcp.(uint32))
3522 //Adding HSIA upstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003523 f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003524 } else {
3525 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003526 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003527 }
3528 } else if _, ok := actionInfo[PopVlan]; ok {
Matteo Scandolo92186242020-06-12 10:54:18 -07003529 logger.Infow("adding-downstream-data-rule", log.Fields{
3530 "intf-id": intfID,
3531 "onu-id": onuID,
3532 "uni-id": uniID,
3533 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003534 if pcp, ok := classifierInfo[VlanPcp]; ok {
3535 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05003536 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003537 pcp.(uint32))
3538 //Adding HSIA downstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003539 f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003540 } else {
3541 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003542 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003543 }
3544 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303545 logger.Errorw("invalid-flow-type-to-handle",
3546 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003547 "intf-id": intfID,
3548 "onu-id": onuID,
3549 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05303550 "classifier": classifierInfo,
3551 "action": actionInfo,
3552 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003553 return
3554 }
3555 // Send Techprofile download event to child device in go routine as it takes time
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003556 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003557}
3558
Gamze Abakafee36392019-10-03 11:17:24 +00003559func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
3560 flowIDList := f.flowsUsedByGemPort[gemPK]
3561 if len(flowIDList) > 1 {
3562 return true
3563 }
3564 return false
3565}
3566
npujarec5762e2020-01-01 14:08:48 +05303567func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3568 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003569 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3570 for _, currentGemPort := range currentGemPorts {
3571 for _, tpGemPort := range tpGemPorts {
3572 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3573 return true, currentGemPort
3574 }
3575 }
3576 }
Girish Gowdra54934262019-11-13 14:19:55 +05303577 if tpInst.InstanceCtrl.Onu == "single-instance" {
3578 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
npujarec5762e2020-01-01 14:08:48 +05303579 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID)
3580 f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID)
Girish Gowdra54934262019-11-13 14:19:55 +05303581
3582 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3583 // still be used on other uni ports.
3584 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3585 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003586 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Shrey Baid26912972020-04-16 21:02:31 +05303587 logger.Debugw("got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303588 for i := 0; i < len(tpInstances); i++ {
3589 tpI := tpInstances[i]
3590 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303591 for _, tpGemPort := range tpGemPorts {
3592 if tpGemPort.GemportID != gemPortID {
Shrey Baid26912972020-04-16 21:02:31 +05303593 logger.Debugw("single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303594 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303595 }
3596 }
3597 }
3598 }
Shrey Baid26912972020-04-16 21:02:31 +05303599 logger.Debug("tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003600 return false, 0
3601}
3602
salmansiddiqui7ac62132019-08-22 03:58:50 +00003603func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003604 for _, field := range flows.GetOfbFields(flow) {
3605 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003606 classifierInfo[EthType] = field.GetEthType()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003607 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003608 } else if field.Type == flows.ETH_DST {
3609 classifierInfo[EthDst] = field.GetEthDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003610 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003611 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003612 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003613 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003614 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003615 classifierInfo[InPort] = field.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003616 logger.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003617 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303618 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00003619 logger.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003620 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003621 classifierInfo[VlanPcp] = field.GetVlanPcp()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003622 logger.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003623 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003624 classifierInfo[UDPDst] = field.GetUdpDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003625 logger.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003626 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003627 classifierInfo[UDPSrc] = field.GetUdpSrc()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003628 logger.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003629 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003630 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003631 logger.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003632 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003633 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003634 logger.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003635 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003636 classifierInfo[Metadata] = field.GetTableMetadata()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003637 logger.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003638 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003639 classifierInfo[TunnelID] = field.GetTunnelId()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003640 logger.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003641 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303642 logger.Errorw("un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003643 return
3644 }
3645 }
3646}
3647
3648func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003649 for _, action := range flows.GetActions(flow) {
3650 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003651 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003652 actionInfo[Output] = out.GetPort()
Shrey Baid26912972020-04-16 21:02:31 +05303653 logger.Debugw("action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003654 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003655 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003656 }
Scott Baker355d1742019-10-24 10:57:52 -07003657 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003658 actionInfo[PopVlan] = true
Girish Kumar2ad402b2020-03-20 19:45:12 +00003659 logger.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003660 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003661 if out := action.GetPush(); out != nil {
3662 if tpid := out.GetEthertype(); tpid != 0x8100 {
Shrey Baid26912972020-04-16 21:02:31 +05303663 logger.Errorw("invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003664 } else {
3665 actionInfo[PushVlan] = true
3666 actionInfo[TPID] = tpid
Girish Kumar2ad402b2020-03-20 19:45:12 +00003667 logger.Debugw("action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303668 log.Fields{
3669 "push-tpid": actionInfo[TPID].(uint32),
3670 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003671 }
3672 }
Scott Baker355d1742019-10-24 10:57:52 -07003673 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003674 if out := action.GetSetField(); out != nil {
3675 if field := out.GetField(); field != nil {
3676 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003677 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003678 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00003679 /*logger.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
Esin Karamanccb714b2019-11-29 15:02:06 +00003680 formulateSetFieldActionInfoFromFlow(field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003681 }
3682 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003683 } else if action.Type == flows.GROUP {
3684 formulateGroupActionInfoFromFlow(action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003685 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003686 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003687 }
3688 }
3689 return nil
3690}
3691
Esin Karamanccb714b2019-11-29 15:02:06 +00003692func formulateSetFieldActionInfoFromFlow(field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
3693 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003694 fieldtype := ofbField.GetType()
3695 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003696 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3697 actionInfo[VlanVid] = vlan & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00003698 logger.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003699 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303700 logger.Error("no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003701 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003702 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3703 pcp := ofbField.GetVlanPcp()
3704 actionInfo[VlanPcp] = pcp
3705 log.Debugw("action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003706 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003707 logger.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003708 }
3709 }
3710}
3711
3712func formulateGroupActionInfoFromFlow(action *ofp.OfpAction, actionInfo map[string]interface{}) {
3713 if action.GetGroup() == nil {
Shrey Baid26912972020-04-16 21:02:31 +05303714 logger.Warn("no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003715 } else {
3716 actionInfo[GroupID] = action.GetGroup().GroupId
Girish Kumar2ad402b2020-03-20 19:45:12 +00003717 logger.Debugw("action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003718 }
3719}
3720
salmansiddiqui7ac62132019-08-22 03:58:50 +00003721func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003722 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Shrey Baid26912972020-04-16 21:02:31 +05303723 logger.Debug("controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003724 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3725 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003726 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003727 classifierInfo[InPort] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303728 logger.Debugw("upstream-pon-to-controller-flow--inport-in-tunnelid",
3729 log.Fields{
3730 "newinport": classifierInfo[InPort].(uint32),
3731 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003732 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303733 return olterrors.NewErrNotFound("child-in-port",
3734 log.Fields{
3735 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3736 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003737 }
3738 }
3739 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303740 logger.Debug("non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003741 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003742 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003743 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003744 actionInfo[Output] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303745 logger.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid",
3746 log.Fields{
3747 "newoutport": actionInfo[Output].(uint32),
3748 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003749 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303750 return olterrors.NewErrNotFound("out-port",
3751 log.Fields{
3752 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3753 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003754 }
3755 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3756 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003757 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003758 classifierInfo[InPort] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303759 logger.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid",
3760 log.Fields{
3761 "newinport": actionInfo[Output].(uint32),
3762 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003763 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303764 return olterrors.NewErrNotFound("nni-port",
3765 log.Fields{
3766 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3767 "in-port": classifierInfo[InPort].(uint32),
3768 "out-port": actionInfo[Output].(uint32),
3769 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003770 }
3771 }
3772 }
3773 return nil
3774}
Gamze Abakafee36392019-10-03 11:17:24 +00003775
Chaitrashree G S90a17952019-11-14 21:51:21 -05003776func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003777 /* Metadata 8 bytes:
3778 Most Significant 2 Bytes = Inner VLAN
3779 Next 2 Bytes = Tech Profile ID(TPID)
3780 Least Significant 4 Bytes = Port ID
3781 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3782 subscriber related flows.
3783 */
3784 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
3785 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003786 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003787 }
3788 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003789 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003790}
3791
3792func appendUnique(slice []uint32, item uint32) []uint32 {
3793 for _, sliceElement := range slice {
3794 if sliceElement == item {
3795 return slice
3796 }
3797 }
3798 return append(slice, item)
3799}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303800
3801// getNniIntfID gets nni intf id from the flow classifier/action
3802func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
3803
3804 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3805 if portType == voltha.Port_PON_OLT {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003806 intfID, err := IntfIDFromNniPortNum(action[Output].(uint32))
3807 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003808 logger.Debugw("invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003809 log.Fields{
3810 "port-number": action[Output].(uint32),
3811 "error": err})
3812 return uint32(0), err
3813 }
Shrey Baid26912972020-04-16 21:02:31 +05303814 logger.Infow("output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303815 return intfID, nil
3816 } else if portType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003817 intfID, err := IntfIDFromNniPortNum(classifier[InPort].(uint32))
3818 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003819 logger.Debugw("invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003820 log.Fields{
3821 "port-number": action[Output].(uint32),
3822 "error": err})
3823 return uint32(0), err
3824 }
Shrey Baid26912972020-04-16 21:02:31 +05303825 logger.Infow("input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303826 return intfID, nil
3827 }
3828 return uint32(0), nil
3829}
3830
3831// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
npujarec5762e2020-01-01 14:08:48 +05303832func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303833 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
3834
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003835 f.onuGemInfoLock[intfID].Lock()
3836 defer f.onuGemInfoLock[intfID].Unlock()
3837
Matt Jeanneret1719a072019-12-20 14:50:14 -05003838 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303839 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003840 if lookupGemPort == gemPort {
Shrey Baid26912972020-04-16 21:02:31 +05303841 logger.Infow("pktin-key/value-found-in-cache--no-need-to-update-kv--assume-both-in-sync",
3842 log.Fields{
3843 "pktinkey": pktInkey,
3844 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003845 return
3846 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303847 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003848 f.packetInGemPort[pktInkey] = gemPort
3849
npujarec5762e2020-01-01 14:08:48 +05303850 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Shrey Baid26912972020-04-16 21:02:31 +05303851 logger.Infow("pktin-key-not-found-in-local-cache-value-is-different--updating-cache-and-kv-store",
3852 log.Fields{
3853 "pktinkey": pktInkey,
3854 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303855 return
3856}
3857
3858// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303859func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003860
3861 f.onuGemInfoLock[intfID].Lock()
3862 defer f.onuGemInfoLock[intfID].Unlock()
3863
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303864 onugem := f.onuGemInfo[intfID]
3865 for idx, onu := range onugem {
3866 if onu.OnuID == onuID {
3867 for _, uni := range onu.UniPorts {
3868 if uni == portNum {
Shrey Baid26912972020-04-16 21:02:31 +05303869 logger.Infow("uni-already-in-cache--no-need-to-update-cache-and-kv-store", log.Fields{"uni": portNum})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303870 return
3871 }
3872 }
3873 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3874 f.onuGemInfo[intfID] = onugem
3875 }
3876 }
npujarec5762e2020-01-01 14:08:48 +05303877 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303878}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303879
npujarec5762e2020-01-01 14:08:48 +05303880func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3881 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303882 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303883 logger.Error("failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303884 return
3885 }
3886 for gem, FlowIDs := range flowIDsList {
3887 gemPK := gemPortKey{intf, uint32(gem)}
3888 f.flowsUsedByGemPort[gemPK] = FlowIDs
3889 }
3890 return
3891}
Esin Karamanccb714b2019-11-29 15:02:06 +00003892
3893//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
3894//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05303895func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
3896 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00003897 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303898 logger.Error("failed-to-get-pon-interface-to-multicast-queue-map")
Esin Karamanccb714b2019-11-29 15:02:06 +00003899 return
3900 }
3901 for intf, queueInfo := range storedMulticastQueueMap {
3902 q := queueInfoBrief{
3903 gemPortID: queueInfo[0],
3904 servicePriority: queueInfo[1],
3905 }
3906 f.interfaceToMcastQueueMap[intf] = &q
3907 }
3908}
3909
3910//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
3911//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
3912//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05303913func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
3914 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00003915 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003916 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00003917 }
3918 if exists {
3919 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
3920 }
3921 return nil, exists, nil
3922}
3923
3924func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
3925 groupDesc := ofp.OfpGroupDesc{
3926 Type: ofp.OfpGroupType_OFPGT_ALL,
3927 GroupId: groupID,
3928 }
3929 groupEntry := ofp.OfpGroupEntry{
3930 Desc: &groupDesc,
3931 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003932 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003933 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00003934 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003935 bucket := ofp.OfpBucket{
3936 Actions: acts,
3937 }
3938 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00003939 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003940 return &groupEntry
3941}