blob: 02e382b245f89d9180c10e4a9b51fdc9de5a6e23 [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
Matteo Scandolo60913ed2020-06-23 19:31:14 -0700221 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache, indexed by IntfId
222 // We need to have a global lock on the onuGemInfo map
223 onuGemInfoLock sync.RWMutex
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700224 pendingFlowDelete sync.Map
Girish Gowdra3d633032019-12-10 16:37:05 +0530225 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Esin Karamanccb714b2019-11-29 15:02:06 +0000226 perUserFlowHandleLock *mapmutex.Mutex
227 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 +0530228}
229
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700230//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
npujarec5762e2020-01-01 14:08:48 +0530231func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
Shrey Baid26912972020-04-16 21:02:31 +0530232 logger.Infow("initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530233 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530234 var err error
235 var idx uint32
236
manikkaraj kbf256be2019-03-25 00:13:48 +0530237 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530238 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000239 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530240 if err = flowMgr.populateTechProfilePerPonPort(); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530241 logger.Errorw("error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530242 return nil
243 }
William Kurkian740a09c2019-10-23 17:07:38 -0400244 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530245 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
246 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530247 ponPorts := rMgr.DevInfo.GetPonPorts()
Matteo Scandolo60913ed2020-06-23 19:31:14 -0700248 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo, ponPorts)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530249 //Load the onugem info cache from kv store on flowmanager start
250 for idx = 0; idx < ponPorts; idx++ {
npujarec5762e2020-01-01 14:08:48 +0530251 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530252 logger.Error("failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530253 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530254 //Load flowID list per gem map per interface from the kvstore.
npujarec5762e2020-01-01 14:08:48 +0530255 flowMgr.loadFlowIDlistForGem(ctx, idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530256 }
Matteo Scandolo60913ed2020-06-23 19:31:14 -0700257 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdra3d633032019-12-10 16:37:05 +0530258 flowMgr.pendingFlowDelete = sync.Map{}
Girish Gowdrab77ded92020-04-08 11:45:05 -0700259 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(300, 100000000, 10000000, 1.1, 0.2)
Esin Karamanccb714b2019-11-29 15:02:06 +0000260 flowMgr.interfaceToMcastQueueMap = make(map[uint32]*queueInfoBrief)
261 //load interface to multicast queue map from kv store
npujarec5762e2020-01-01 14:08:48 +0530262 flowMgr.loadInterfaceToMulticastQueueMap(ctx)
Shrey Baid26912972020-04-16 21:02:31 +0530263 logger.Info("initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530264 return &flowMgr
265}
266
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700267func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700268 if direction == Upstream {
Shrey Baid26912972020-04-16 21:02:31 +0530269 logger.Debugw("upstream-flow-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700270 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700271 } else if direction == Downstream {
Shrey Baid26912972020-04-16 21:02:31 +0530272 logger.Debugw("downstream-flow-not-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700273 return uint64(flowID), nil
Esin Karamanccb714b2019-11-29 15:02:06 +0000274 } else if direction == Multicast {
Shrey Baid26912972020-04-16 21:02:31 +0530275 logger.Debugw("multicast-flow-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000276 return 0x2<<15 | uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400277 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530278 return 0, olterrors.NewErrInvalidValue(log.Fields{"direction": direction}, nil).Log()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400279 }
280}
281
npujarec5762e2020-01-01 14:08:48 +0530282func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Shrey Baid26912972020-04-16 21:02:31 +0530283 logger.Debugw("registering-flow-for-device ",
284 log.Fields{
285 "flow": flowFromCore,
286 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000287 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
288 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
289 if !ok {
290 flowIDList = []uint32{deviceFlow.FlowId}
291 }
292 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
293 f.flowsUsedByGemPort[gemPK] = flowIDList
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530294 // update the flowids for a gem to the KVstore
npujarec5762e2020-01-01 14:08:48 +0530295 f.resourceMgr.UpdateFlowIDsForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400296}
297
npujarec5762e2020-01-01 14:08:48 +0530298func (f *OpenOltFlowMgr) divideAndAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000299 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
300 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000301 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530302 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700303 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530304
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700305 logger.Infow("dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530306 "device-id": f.deviceHandler.device.Id,
307 "intf-id": intfID,
308 "onu-id": onuID,
309 "uni-id": uniID,
310 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700311 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530312 "action": actionInfo,
313 "usmeter-iD": UsMeterID,
314 "dsmeter-iD": DsMeterID,
315 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400316 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
317 // is because the flow is an NNI flow and there would be no onu resources associated with it
318 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400319 if onuID <= 0 {
Shrey Baid26912972020-04-16 21:02:31 +0530320 logger.Errorw("no-onu-id-for-flow",
321 log.Fields{
322 "port-no": portNo,
323 "classifer": classifierInfo,
324 "action": actionInfo,
325 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530326 return
327 }
328
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700329 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Shrey Baid26912972020-04-16 21:02:31 +0530330 logger.Debugw("uni-port-path", log.Fields{
331 "uni": uni,
332 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530333
334 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
335 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700336 logger.Debugw("dividing-flow-create-tcont-gem-ports", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530337 "device-id": f.deviceHandler.device.Id,
338 "intf-id": intfID,
339 "onu-id": onuID,
340 "uni-id": uniID,
341 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700342 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530343 "action": actionInfo,
344 "usmeter-id": UsMeterID,
345 "dsmeter-id": DsMeterID,
346 "tp-id": TpID})
npujarec5762e2020-01-01 14:08:48 +0530347 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530348 if allocID == 0 || gemPorts == nil || TpInst == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000349 logger.Error("alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530350 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
351 return
352 }
353 args := make(map[string]uint32)
354 args[IntfID] = intfID
355 args[OnuID] = onuID
356 args[UniID] = uniID
357 args[PortNo] = portNo
358 args[AllocID] = allocID
359
360 /* Flows can be added specific to gemport if p-bits are received.
361 * If no pbit mentioned then adding flows for all gemports
362 */
npujarec5762e2020-01-01 14:08:48 +0530363 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530364 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
365 } else {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700366 logger.Errorw("failed-to-acquire-per-user-flow-handle-lock",
Shrey Baid26912972020-04-16 21:02:31 +0530367 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700368 "intf-id": intfID,
369 "onu-id": onuID,
370 "uni-id": uniID,
371 "flow-id": flow.Id,
372 "flow-cookie": flow.Cookie,
373 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400374 return
375 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530376}
377
salmansiddiqui7ac62132019-08-22 03:58:50 +0000378// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530379func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400380
Shrey Baid26912972020-04-16 21:02:31 +0530381 logger.Debugw("CreateSchedulerQueues",
382 log.Fields{"dir": sq.direction,
383 "intf-id": sq.intfID,
384 "onu-id": sq.onuID,
385 "uni-id": sq.uniID,
386 "tp-id": sq.tpID,
387 "meter-id": sq.meterID,
388 "tp-inst": sq.tpInst,
389 "flowmetadata": sq.flowMetadata,
390 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400391
Gamze Abakafee36392019-10-03 11:17:24 +0000392 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000393 if err != nil {
394 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400395 }
396
397 /* Lets make a simple assumption that if the meter-id is present on the KV store,
398 * then the scheduler and queues configuration is applied on the OLT device
399 * in the given direction.
400 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000401
Manikkaraj kb1d51442019-07-23 10:41:02 -0400402 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530403 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400404 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530405 return olterrors.NewErrNotFound("meter",
406 log.Fields{"intf-id": sq.intfID,
407 "onu-id": sq.onuID,
408 "uni-id": sq.uniID,
409 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400410 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000411
Manikkaraj kb1d51442019-07-23 10:41:02 -0400412 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000413 if KvStoreMeter.MeterId == sq.meterID {
Shrey Baid26912972020-04-16 21:02:31 +0530414 logger.Debugw("scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400415 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400416 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530417 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800418 "unsupported": "meter-id",
419 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530420 "meter-id-in-flow": sq.meterID,
421 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400422 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000423
Shrey Baid26912972020-04-16 21:02:31 +0530424 logger.Debugw("meter-does-not-exist-creating-new",
425 log.Fields{
426 "meter-id": sq.meterID,
427 "direction": Direction,
428 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000429
Gamze Abakafee36392019-10-03 11:17:24 +0000430 if sq.direction == tp_pb.Direction_UPSTREAM {
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700431 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000432 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700433 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400434 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000435
436 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530437 return olterrors.NewErrNotFound("scheduler-config",
438 log.Fields{
439 "intf-id": sq.intfID,
440 "direction": sq.direction,
441 "tp-inst": sq.tpInst,
442 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000443 }
444
Manikkaraj kb1d51442019-07-23 10:41:02 -0400445 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000446 if sq.flowMetadata != nil {
447 for _, meter := range sq.flowMetadata.Meters {
448 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400449 meterConfig = meter
Shrey Baid26912972020-04-16 21:02:31 +0530450 logger.Debugw("found-meter-config-from-flowmetadata",
451 log.Fields{"meterConfig": meterConfig,
452 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400453 break
454 }
455 }
456 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530457 logger.Errorw("flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400458 }
459 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530460 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800461 "reason": "Could-not-get-meterbands-from-flowMetadata",
462 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530463 "meter-id": sq.meterID,
464 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400465 } else if len(meterConfig.Bands) < MaxMeterBand {
Shrey Baid26912972020-04-16 21:02:31 +0530466 logger.Errorw("invalid-number-of-bands-in-meter",
467 log.Fields{"Bands": meterConfig.Bands,
468 "meter-id": sq.meterID,
469 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530470 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800471 "reason": "Invalid-number-of-bands-in-meter",
472 "meterband-count": len(meterConfig.Bands),
473 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530474 "meter-id": sq.meterID,
475 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400476 }
477 cir := meterConfig.Bands[0].Rate
478 cbs := meterConfig.Bands[0].BurstSize
479 eir := meterConfig.Bands[1].Rate
480 ebs := meterConfig.Bands[1].BurstSize
481 pir := cir + eir
482 pbs := cbs + ebs
483 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
484
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700485 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000486 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400487
npujarec5762e2020-01-01 14:08:48 +0530488 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530489 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
490 log.Fields{"intf-id": sq.intfID,
491 "direction": sq.direction,
492 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400493 }
494
salmansiddiqui7ac62132019-08-22 03:58:50 +0000495 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400496 * store the meter id on the KV store, for further reference.
497 */
npujarec5762e2020-01-01 14:08:48 +0530498 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 +0530499 return olterrors.NewErrAdapter("failed-updating-meter-id",
500 log.Fields{"onu-id": sq.onuID,
501 "meter-id": sq.meterID,
502 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503 }
Shrey Baid26912972020-04-16 21:02:31 +0530504 logger.Infow("updated-meter-info-into-kv-store-successfully",
505 log.Fields{"direction": Direction,
506 "Meter": meterConfig,
507 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400508 return nil
509}
510
npujarec5762e2020-01-01 14:08:48 +0530511func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000512
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700513 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000514
515 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530516 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
517 log.Fields{"intf-id": sq.intfID,
518 "direction": sq.direction,
519 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000520 }
521
Shrey Baid26912972020-04-16 21:02:31 +0530522 logger.Debugw("sending-traffic-scheduler-create-to-device",
523 log.Fields{
524 "direction": sq.direction,
525 "TrafficScheds": TrafficSched,
526 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530527 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000528 IntfId: sq.intfID, OnuId: sq.onuID,
529 UniId: sq.uniID, PortNo: sq.uniPort,
530 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000531 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000532 }
Shrey Baid26912972020-04-16 21:02:31 +0530533 logger.Infow("successfully-created-traffic-schedulers", log.Fields{
534 "direction": sq.direction,
535 "traffic-queues": trafficQueues,
536 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000537
538 // On receiving the CreateTrafficQueues request, the driver should create corresponding
539 // downstream queues.
Shrey Baid26912972020-04-16 21:02:31 +0530540 logger.Debugw("sending-traffic-queues-create-to-device",
541 log.Fields{"direction": sq.direction,
542 "traffic-queues": trafficQueues,
543 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530544 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000545 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
546 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000547 TrafficQueues: trafficQueues,
548 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530549 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000550 }
Shrey Baid26912972020-04-16 21:02:31 +0530551 logger.Infow("successfully-created-traffic-schedulers", log.Fields{
552 "direction": sq.direction,
553 "traffic-queues": trafficQueues,
554 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000555
Esin Karamanccb714b2019-11-29 15:02:06 +0000556 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700557 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000558 if len(multicastTrafficQueues) > 0 {
559 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
560 //assumed that there is only one queue per PON for the multicast service
561 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
562 //just put it in interfaceToMcastQueueMap to use for building group members
Shrey Baid26912972020-04-16 21:02:31 +0530563 logger.Debugw("multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000564 multicastQueuePerPonPort := multicastTrafficQueues[0]
565 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
566 gemPortID: multicastQueuePerPonPort.GemportId,
567 servicePriority: multicastQueuePerPonPort.Priority,
568 }
569 //also store the queue info in kv store
npujarec5762e2020-01-01 14:08:48 +0530570 f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID,
Esin Karamanccb714b2019-11-29 15:02:06 +0000571 multicastQueuePerPonPort.GemportId,
572 multicastQueuePerPonPort.Priority)
Shrey Baid26912972020-04-16 21:02:31 +0530573
574 logger.Infow("multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000575 }
576 }
577 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000578 return nil
579}
580
salmansiddiqui7ac62132019-08-22 03:58:50 +0000581// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530582func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400583
584 var Direction string
585 var SchedCfg *tp_pb.SchedulerConfig
586 var err error
Shrey Baid26912972020-04-16 21:02:31 +0530587 logger.Infow("removing-schedulers-and-queues-in-olt",
588 log.Fields{
589 "direction": sq.direction,
590 "intf-id": sq.intfID,
591 "onu-id": sq.onuID,
592 "uni-id": sq.uniID,
593 "uni-port": sq.uniPort,
594 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000595 if sq.direction == tp_pb.Direction_UPSTREAM {
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700596 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400597 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000598 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700599 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400600 Direction = "downstream"
601 }
602
Girish Kumar8f73fe02019-12-09 13:19:37 +0000603 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530604 return olterrors.NewErrNotFound("scheduler-config",
605 log.Fields{
606 "int-id": sq.intfID,
607 "direction": sq.direction,
608 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000609 }
610
npujarec5762e2020-01-01 14:08:48 +0530611 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400612 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530613 return olterrors.NewErrNotFound("meter",
614 log.Fields{
615 "onu-id": sq.onuID,
616 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400617 }
618 if KVStoreMeter == nil {
Shrey Baid26912972020-04-16 21:02:31 +0530619 logger.Warnw("no-meter-installed-yet",
620 log.Fields{
621 "direction": Direction,
622 "intf-id": sq.intfID,
623 "onu-id": sq.onuID,
624 "uni-id": sq.uniID,
625 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400626 return nil
627 }
628 cir := KVStoreMeter.Bands[0].Rate
629 cbs := KVStoreMeter.Bands[0].BurstSize
630 eir := KVStoreMeter.Bands[1].Rate
631 ebs := KVStoreMeter.Bands[1].BurstSize
632 pir := cir + eir
633 pbs := cbs + ebs
634
635 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
636
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700637 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000638 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000639
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700640 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000641 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530642 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
643 log.Fields{
644 "intf-id": sq.intfID,
645 "direction": sq.direction,
646 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000647 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400648
npujarec5762e2020-01-01 14:08:48 +0530649 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000650 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
651 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000652 TrafficQueues: TrafficQueues,
653 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000654 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530655 log.Fields{
656 "intf-id": sq.intfID,
657 "traffic-queues": TrafficQueues,
658 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400659 }
Shrey Baid26912972020-04-16 21:02:31 +0530660 logger.Infow("removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530661 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000662 IntfId: sq.intfID, OnuId: sq.onuID,
663 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400664 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000665 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530666 log.Fields{
667 "intf-id": sq.intfID,
668 "traffic-schedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400669 }
670
Shrey Baid26912972020-04-16 21:02:31 +0530671 logger.Infow("removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000672
673 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400674 * delete the meter id on the KV store.
675 */
npujarec5762e2020-01-01 14:08:48 +0530676 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400677 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530678 return olterrors.NewErrAdapter("unable-to-remove-meter",
679 log.Fields{
680 "onu": sq.onuID,
681 "meter": KVStoreMeter.MeterId,
682 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400683 }
Shrey Baid26912972020-04-16 21:02:31 +0530684 logger.Infow("removed-meter-from-KV-store-successfully",
685 log.Fields{
686 "meter-id": KVStoreMeter.MeterId,
687 "dir": Direction,
688 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400689 return err
690}
691
Gamze Abakafee36392019-10-03 11:17:24 +0000692// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700693func (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 +0000694 var allocIDs []uint32
695 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530696 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530697 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000698 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000699
npujarec5762e2020-01-01 14:08:48 +0530700 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
701 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400702
703 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530704
Shrey Baid26912972020-04-16 21:02:31 +0530705 logger.Debugw("creating-new-tcont-and-gem", log.Fields{
706 "intf-id": intfID,
707 "onu-id": onuID,
708 "uni-id": uniID,
709 "device-id": f.deviceHandler.device.Id,
710 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530711
Manikkaraj kb1d51442019-07-23 10:41:02 -0400712 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530713 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000714 if techProfileInstance == nil {
Shrey Baid26912972020-04-16 21:02:31 +0530715 logger.Infow("tp-instance-not-found--creating-new",
716 log.Fields{
717 "path": tpPath,
718 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530719 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000720 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530721 // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +0530722 logger.Errorw("tp-instance-create-failed",
723 log.Fields{
724 "error": err,
725 "tp-id": TpID,
726 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000727 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530728 }
npujarec5762e2020-01-01 14:08:48 +0530729 f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530730 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530731 logger.Debugw("tech-profile-instance-already-exist-for-given port-name",
732 log.Fields{
733 "uni": uni,
734 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530735 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530736 }
Gamze Abakafee36392019-10-03 11:17:24 +0000737
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700738 switch tpInst := techProfileInstance.(type) {
739 case *tp.TechProfile:
740 if UsMeterID != 0 {
741 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
742 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
743 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
744 logger.Errorw("CreateSchedulerQueues-failed-upstream",
745 log.Fields{
746 "error": err,
747 "meter-id": UsMeterID,
748 "device-id": f.deviceHandler.device.Id})
749 return 0, nil, nil
750 }
751 }
752 if DsMeterID != 0 {
753 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
754 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
755 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
756 logger.Errorw("CreateSchedulerQueues-failed-downstream",
757 log.Fields{
758 "error": err,
759 "meter-id": DsMeterID,
760 "device-id": f.deviceHandler.device.Id})
761 return 0, nil, nil
762 }
763 }
764 allocID := tpInst.UsScheduler.AllocID
765 for _, gem := range tpInst.UpstreamGemPortAttributeList {
766 gemPortIDs = append(gemPortIDs, gem.GemportID)
767 }
768 allocIDs = appendUnique(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000769
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700770 if tpInstanceExists {
771 return allocID, gemPortIDs, techProfileInstance
772 }
773
774 for _, gemPortID := range gemPortIDs {
775 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
776 }
777 logger.Infow("allocated-tcont-and-gem-ports",
778 log.Fields{
779 "alloc-ids": allocIDs,
780 "gemports": allgemPortIDs,
781 "device-id": f.deviceHandler.device.Id})
782 // Send Tconts and GEM ports to KV store
783 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530784 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700785 case *tp.EponProfile:
786 // CreateSchedulerQueues for EPON needs to be implemented here
787 // when voltha-protos for EPON is completed.
788 allocID := tpInst.AllocID
789 for _, gem := range tpInst.UpstreamQueueAttributeList {
790 gemPortIDs = append(gemPortIDs, gem.GemportID)
791 }
792 allocIDs = appendUnique(allocIDs, allocID)
793
794 if tpInstanceExists {
795 return allocID, gemPortIDs, techProfileInstance
796 }
797
798 for _, gemPortID := range gemPortIDs {
799 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
800 }
801 logger.Infow("allocated-tcont-and-gem-ports",
802 log.Fields{
803 "alloc-ids": allocIDs,
804 "gemports": allgemPortIDs,
805 "device-id": f.deviceHandler.device.Id})
806 // Send Tconts and GEM ports to KV store
807 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
808 return allocID, gemPortIDs, techProfileInstance
809 default:
810 logger.Errorw("unknown-tech",
811 log.Fields{
812 "tpInst": tpInst})
813 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530814 }
815
manikkaraj kbf256be2019-03-25 00:13:48 +0530816}
817
npujarec5762e2020-01-01 14:08:48 +0530818func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530819
Shrey Baid26912972020-04-16 21:02:31 +0530820 logger.Debugw("storing-allocated-tconts-and-gem-ports-into-KV-store",
821 log.Fields{
822 "intf-id": intfID,
823 "onu-id": onuID,
824 "uni-id": uniID,
825 "alloc-id": allocID,
826 "gemport-ids": gemPortIDs,
827 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530828 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530829 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530830 logger.Errorw("error-while-uploading-allocid-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530831 }
npujarec5762e2020-01-01 14:08:48 +0530832 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530833 logger.Errorw("error-while-uploading-gemports-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530834 }
npujarec5762e2020-01-01 14:08:48 +0530835 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530836 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 +0530837 }
Shrey Baid26912972020-04-16 21:02:31 +0530838 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 -0400839 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530840 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400841 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530842}
843
844func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000845 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530846 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000847 for _, intfID := range techRange.IntfIds {
848 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400849 tpCount++
Shrey Baid26912972020-04-16 21:02:31 +0530850 logger.Debugw("init-tech-profile-done",
851 log.Fields{
852 "intf-id": intfID,
853 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530854 }
855 }
856 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400857 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530858 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530859 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800860 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530861 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
862 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530863 }
Shrey Baid26912972020-04-16 21:02:31 +0530864 logger.Infow("populated-techprofile-for-ponports-successfully",
865 log.Fields{
866 "numofTech": tpCount,
867 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
868 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530869 return nil
870}
871
npujarec5762e2020-01-01 14:08:48 +0530872func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530873 portNo uint32, uplinkClassifier map[string]interface{},
874 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000875 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700876 uplinkClassifier[PacketTagType] = SingleTag
Shrey Baid26912972020-04-16 21:02:31 +0530877 logger.Debugw("adding-upstream-data-flow",
878 log.Fields{
879 "uplinkClassifier": uplinkClassifier,
880 "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800881 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000882 Upstream, logicalFlow, allocID, gemportID, tpID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530883 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530884}
885
npujarec5762e2020-01-01 14:08:48 +0530886func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530887 portNo uint32, downlinkClassifier map[string]interface{},
888 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000889 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700890 downlinkClassifier[PacketTagType] = DoubleTag
Shrey Baid26912972020-04-16 21:02:31 +0530891 logger.Debugw("adding-downstream-data-flow",
892 log.Fields{
893 "downlinkClassifier": downlinkClassifier,
894 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400895 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
896 if vlan, exists := downlinkClassifier[VlanVid]; exists {
897 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700898 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400899 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
Shrey Baid26912972020-04-16 21:02:31 +0530900 logger.Infow("ignoring-dl-trap-device-flow-from-core",
901 log.Fields{
902 "flow": logicalFlow,
903 "device-id": f.deviceHandler.device.Id,
904 "onu-id": onuID,
905 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800906 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400907 }
908 }
909 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530910 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400911
Manikkaraj k884c1242019-04-11 16:26:42 +0530912 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700913 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400914 // vlan_vid is a uint32. must be type asserted as such or conversion fails
915 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530916 if ok {
917 downlinkAction[VlanVid] = dlClVid & 0xfff
918 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530919 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530920 "reason": "failed-to-convert-vlanid-classifier",
921 "vlan-id": VlanVid,
922 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530923 }
924
David K. Bainbridge794735f2020-02-11 21:01:37 -0800925 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000926 Downstream, logicalFlow, allocID, gemportID, tpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530927}
928
npujarec5762e2020-01-01 14:08:48 +0530929func (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 +0530930 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000931 allocID uint32, gemPortID uint32, tpID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530932 /* One of the OLT platform (Broadcom BAL) requires that symmetric
933 flows require the same flow_id to be used across UL and DL.
934 Since HSIA flow is the only symmetric flow currently, we need to
935 re-use the flow_id across both direction. The 'flow_category'
936 takes priority over flow_cookie to find any available HSIA_FLOW
937 id for the ONU.
938 */
Shrey Baid26912972020-04-16 21:02:31 +0530939 logger.Infow("adding-hsia-flow",
940 log.Fields{
941 "intf-id": intfID,
942 "onu-id": onuID,
943 "uni-id": uniID,
944 "device-id": f.deviceHandler.device.Id,
945 "classifier": classifier,
946 "action": action,
947 "direction": direction,
948 "alloc-id": allocID,
949 "gemport-id": gemPortID,
950 "logicalflow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530951 var vlanPbit uint32 = 0xff // means no pbit
Gamze Abaka724d0852020-03-18 12:10:24 +0000952 var vlanVid uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400953 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000954 vlanPbit = classifier[VlanPcp].(uint32)
Shrey Baid26912972020-04-16 21:02:31 +0530955 logger.Debugw("found-pbit-in-flow",
956 log.Fields{
957 "vlan-pbit": vlanPbit,
958 "intf-id": intfID,
959 "onu-id": onuID,
960 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800961 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530962 logger.Debugw("pbit-not-found-in-flow",
963 log.Fields{
964 "vlan-pcp": VlanPcp,
965 "intf-id": intfID,
966 "onu-id": onuID,
967 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400968 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000969 if _, ok := classifier[VlanVid]; ok {
970 vlanVid = classifier[VlanVid].(uint32)
Shrey Baid26912972020-04-16 21:02:31 +0530971 log.Debugw("found-vlan-in-the-flow",
972 log.Fields{
973 "vlan-vid": vlanVid,
974 "intf-id": intfID,
975 "onu-id": onuID,
976 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000977 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700978 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530979 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +0530980 logger.Infow("flow-already-exists",
981 log.Fields{
982 "device-id": f.deviceHandler.device.Id,
983 "intf-id": intfID,
984 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800985 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530986 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000987 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530988 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530989 return olterrors.NewErrNotFound("hsia-flow-id",
990 log.Fields{
991 "direction": direction,
992 "device-id": f.deviceHandler.device.Id,
993 "intf-id": intfID,
994 "onu-id": onuID,
995 }, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530996 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800997 classifierProto, err := makeOpenOltClassifierField(classifier)
998 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530999 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301000 }
Shrey Baid26912972020-04-16 21:02:31 +05301001 logger.Debugw("created-classifier-proto",
1002 log.Fields{
1003 "classifier": *classifierProto,
1004 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001005 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001006 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301007 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301008 }
Shrey Baid26912972020-04-16 21:02:31 +05301009 logger.Debugw("created-action-proto",
1010 log.Fields{
1011 "action": *actionProto,
1012 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001013 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301014 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301015 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001016 log.Fields{
1017 "classifier": classifier,
1018 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301019 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001020 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301021 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001022 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
1023 OnuId: int32(onuID),
1024 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +00001025 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +05301026 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001027 AllocId: int32(allocID),
1028 NetworkIntfId: int32(networkIntfID),
1029 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +05301030 Classifier: classifierProto,
1031 Action: actionProto,
1032 Priority: int32(logicalFlow.Priority),
1033 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001034 PortNo: portNo,
1035 TechProfileId: tpID,
1036 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001037 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301038 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301039 }
Shrey Baid26912972020-04-16 21:02:31 +05301040 logger.Infow("hsia-flow-added-to-device-successfully",
1041 log.Fields{"direction": direction,
1042 "device-id": f.deviceHandler.device.Id,
1043 "flow": flow,
1044 "intf-id": intfID,
1045 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001046 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
1047 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1048 flow.OnuId,
1049 flow.UniId,
1050 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301051 return olterrors.NewErrPersistence("update", "flow", flowID,
1052 log.Fields{
1053 "flow": flow,
1054 "device-id": f.deviceHandler.device.Id,
1055 "intf-id": intfID,
1056 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001057 }
1058 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301059}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001060
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001061func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1062 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1063 gemPortID uint32, tpID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301064
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301065 networkIntfID, err := getNniIntfID(classifier, action)
1066 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301067 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001068 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301069 "action": action,
1070 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001071 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301072 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301073
1074 // Clear the action map
1075 for k := range action {
1076 delete(action, k)
1077 }
1078
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001079 action[TrapToHost] = true
1080 classifier[UDPSrc] = uint32(68)
1081 classifier[UDPDst] = uint32(67)
1082 classifier[PacketTagType] = SingleTag
1083 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301084
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001085 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301086 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301087 logger.Infow("flow-exists--not-re-adding",
1088 log.Fields{
1089 "device-id": f.deviceHandler.device.Id,
1090 "intf-id": intfID,
1091 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001092 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301093 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301094
David K. Bainbridge794735f2020-02-11 21:01:37 -08001095 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 +05301096
1097 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301098 return olterrors.NewErrNotFound("flow",
1099 log.Fields{
1100 "interface-id": intfID,
1101 "gem-port": gemPortID,
1102 "cookie": flowStoreCookie,
1103 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001104 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301105 }
1106
Shrey Baid26912972020-04-16 21:02:31 +05301107 logger.Debugw("creating-ul-dhcp-flow",
1108 log.Fields{
1109 "ul_classifier": classifier,
1110 "ul_action": action,
1111 "uplinkFlowId": flowID,
1112 "intf-id": intfID,
1113 "onu-id": onuID,
1114 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301115
David K. Bainbridge794735f2020-02-11 21:01:37 -08001116 classifierProto, err := makeOpenOltClassifierField(classifier)
1117 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301118 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301119 }
Shrey Baid26912972020-04-16 21:02:31 +05301120 logger.Debugw("created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001121 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001122 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301123 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301124 }
1125
David K. Bainbridge794735f2020-02-11 21:01:37 -08001126 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001127 OnuId: int32(onuID),
1128 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301129 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001130 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001131 AllocId: int32(allocID),
1132 NetworkIntfId: int32(networkIntfID),
1133 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301134 Classifier: classifierProto,
1135 Action: actionProto,
1136 Priority: int32(logicalFlow.Priority),
1137 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001138 PortNo: portNo,
1139 TechProfileId: tpID,
1140 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001141 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301142 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001143 }
Shrey Baid26912972020-04-16 21:02:31 +05301144 logger.Infow("dhcp-ul-flow-added-to-device-successfully",
1145 log.Fields{
1146 "device-id": f.deviceHandler.device.Id,
1147 "flow-id": flowID,
1148 "intf-id": intfID,
1149 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001150 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
1151 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
1152 dhcpFlow.OnuId,
1153 dhcpFlow.UniId,
1154 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301155 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1156 log.Fields{
1157 "flow": dhcpFlow,
1158 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301159 }
1160
David K. Bainbridge794735f2020-02-11 21:01:37 -08001161 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301162}
1163
Esin Karamanae41e2b2019-12-17 18:13:13 +00001164//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301165func (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 +00001166 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32) error {
1167 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001168}
1169
1170//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301171func (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 +00001172 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string, tpID uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001173
1174 networkIntfID, err := getNniIntfID(classifier, action)
1175 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301176 return olterrors.NewErrNotFound("nni-interface-id",
1177 log.Fields{
1178 "classifier": classifier,
1179 "action": action,
1180 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001181 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001182 }
1183
1184 // Clear the action map
1185 for k := range action {
1186 delete(action, k)
1187 }
1188
1189 action[TrapToHost] = true
1190 classifier[PacketTagType] = SingleTag
1191 delete(classifier, VlanVid)
1192
1193 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301194 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301195 logger.Infow("flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001196 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001197 }
1198
npujarec5762e2020-01-01 14:08:48 +05301199 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 +00001200
1201 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301202 return olterrors.NewErrNotFound("flow-id",
1203 log.Fields{
1204 "intf-id": intfID,
1205 "oni-id": onuID,
1206 "cookie": flowStoreCookie,
1207 "flow-type": flowType,
1208 "device-id": f.deviceHandler.device.Id,
1209 "onu-id": onuID},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001210 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001211 }
1212
Shrey Baid26912972020-04-16 21:02:31 +05301213 logger.Debugw("creating-upstream-trap-flow",
1214 log.Fields{
1215 "ul_classifier": classifier,
1216 "ul_action": action,
1217 "uplinkFlowId": flowID,
1218 "flowType": flowType,
1219 "device-id": f.deviceHandler.device.Id,
1220 "intf-id": intfID,
1221 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001222
David K. Bainbridge794735f2020-02-11 21:01:37 -08001223 classifierProto, err := makeOpenOltClassifierField(classifier)
1224 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301225 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001226 }
Shrey Baid26912972020-04-16 21:02:31 +05301227 logger.Debugw("created-classifier-proto",
1228 log.Fields{
1229 "classifier": *classifierProto,
1230 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001231 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001232 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301233 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001234 }
1235
David K. Bainbridge794735f2020-02-11 21:01:37 -08001236 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001237 OnuId: int32(onuID),
1238 UniId: int32(uniID),
1239 FlowId: flowID,
1240 FlowType: Upstream,
1241 AllocId: int32(allocID),
1242 NetworkIntfId: int32(networkIntfID),
1243 GemportId: int32(gemPortID),
1244 Classifier: classifierProto,
1245 Action: actionProto,
1246 Priority: int32(logicalFlow.Priority),
1247 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001248 PortNo: portNo,
1249 TechProfileId: tpID,
1250 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001251
David K. Bainbridge794735f2020-02-11 21:01:37 -08001252 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301253 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 -08001254 }
Shrey Baid26912972020-04-16 21:02:31 +05301255 logger.Infof("%s ul-flow-added-to-device-successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001256
David K. Bainbridge794735f2020-02-11 21:01:37 -08001257 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
1258 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1259 flow.OnuId,
1260 flow.UniId,
1261 flow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301262 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 +00001263 }
1264
David K. Bainbridge794735f2020-02-11 21:01:37 -08001265 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001266}
1267
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001268// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001269func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1270 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1271 gemPortID uint32, vlanID uint32, tpID uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05301272 logger.Infow("adding-eapol-to-device",
1273 log.Fields{
1274 "intf-id": intfID,
1275 "onu-id": onuID,
1276 "port-no": portNo,
1277 "alloc-id": allocID,
1278 "gemport-id": gemPortID,
1279 "vlan-id": vlanID,
1280 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301281
1282 uplinkClassifier := make(map[string]interface{})
1283 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301284
manikkaraj kbf256be2019-03-25 00:13:48 +05301285 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001286 uplinkClassifier[EthType] = uint32(EapEthType)
1287 uplinkClassifier[PacketTagType] = SingleTag
1288 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001289 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301290 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001291 uplinkAction[TrapToHost] = true
1292 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301293 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301294 logger.Infow("flow-exists-not-re-adding", log.Fields{
1295 "device-id": f.deviceHandler.device.Id,
1296 "onu-id": onuID,
1297 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001298 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301299 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301300 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +00001301 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +05301302 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301303 return olterrors.NewErrNotFound("flow-id",
1304 log.Fields{
1305 "intf-id": intfID,
1306 "onu-id": onuID,
1307 "coookie": flowStoreCookie,
1308 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001309 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301310 }
Shrey Baid26912972020-04-16 21:02:31 +05301311 logger.Debugw("creating-ul-eapol-flow",
1312 log.Fields{
1313 "ul_classifier": uplinkClassifier,
1314 "ul_action": uplinkAction,
1315 "uplinkFlowId": uplinkFlowID,
1316 "device-id": f.deviceHandler.device.Id,
1317 "intf-id": intfID,
1318 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301319
David K. Bainbridge794735f2020-02-11 21:01:37 -08001320 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1321 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301322 return olterrors.NewErrInvalidValue(log.Fields{
1323 "classifier": uplinkClassifier,
1324 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301325 }
Shrey Baid26912972020-04-16 21:02:31 +05301326 logger.Debugw("created-classifier-proto",
1327 log.Fields{
1328 "classifier": *classifierProto,
1329 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001330 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001331 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301332 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301333 }
Shrey Baid26912972020-04-16 21:02:31 +05301334 logger.Debugw("created-action-proto",
1335 log.Fields{
1336 "action": *actionProto,
1337 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001338 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301339 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301340 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001341 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301342 "action": action,
1343 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001344 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301345 }
1346
David K. Bainbridge794735f2020-02-11 21:01:37 -08001347 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001348 OnuId: int32(onuID),
1349 UniId: int32(uniID),
1350 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001351 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001352 AllocId: int32(allocID),
1353 NetworkIntfId: int32(networkIntfID),
1354 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301355 Classifier: classifierProto,
1356 Action: actionProto,
1357 Priority: int32(logicalFlow.Priority),
1358 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001359 PortNo: portNo,
1360 TechProfileId: tpID,
1361 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001362 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301363 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001364 }
Shrey Baid26912972020-04-16 21:02:31 +05301365 logger.Infow("eapol-ul-flow-added-to-device-successfully",
1366 log.Fields{
1367 "device-id": f.deviceHandler.device.Id,
1368 "onu-id": onuID,
1369 "intf-id": intfID,
1370 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001371 flowCategory := "EAPOL"
1372 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1373 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1374 upstreamFlow.OnuId,
1375 upstreamFlow.UniId,
1376 upstreamFlow.FlowId,
1377 /* lowCategory, */
1378 flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301379 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1380 log.Fields{
1381 "flow": upstreamFlow,
1382 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301383 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001384 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301385}
1386
David K. Bainbridge794735f2020-02-11 21:01:37 -08001387func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001388 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001389
1390 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1391 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1392 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001393 if vlanID != ReservedVlan {
1394 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001395 classifier.OVid = vid
1396 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301397 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001398 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1399 vid := uint32(metadata)
1400 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001401 classifier.IVid = vid
1402 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301403 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301404 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001405 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301406 classifier.OPbits = vlanPcp
1407 } else {
1408 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301409 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001410 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1411 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1412 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1413 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001414 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001415 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1416 classifier.PktTagType = pktTagType
1417
1418 switch pktTagType {
1419 case SingleTag:
1420 case DoubleTag:
1421 case Untagged:
1422 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001423 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301424 }
1425 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001426 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301427}
1428
Gamze Abaka724d0852020-03-18 12:10:24 +00001429func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001430 var actionCmd openoltpb2.ActionCmd
1431 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301432 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001433 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301434 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001435 if _, ok := actionInfo[VlanPcp]; ok {
1436 action.Cmd.RemarkInnerPbits = true
1437 action.IPbits = actionInfo[VlanPcp].(uint32)
1438 if _, ok := actionInfo[VlanVid]; ok {
1439 action.Cmd.TranslateInnerTag = true
1440 action.IVid = actionInfo[VlanVid].(uint32)
1441 }
1442 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001443 } else if _, ok := actionInfo[PushVlan]; ok {
1444 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301445 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001446 if _, ok := actionInfo[VlanPcp]; ok {
1447 action.OPbits = actionInfo[VlanPcp].(uint32)
1448 action.Cmd.RemarkOuterPbits = true
1449 if _, ok := classifierInfo[VlanVid]; ok {
1450 action.IVid = classifierInfo[VlanVid].(uint32)
1451 action.Cmd.TranslateInnerTag = true
1452 }
1453 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001454 } else if _, ok := actionInfo[TrapToHost]; ok {
1455 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301456 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001457 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301458 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001459 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301460}
1461
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001462// getTPpath return the ETCD path for a given UNI port
1463func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uniPath string, TpID uint32) string {
1464 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301465}
1466
Gamze Abakafee36392019-10-03 11:17:24 +00001467// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301468func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1469 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001470 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1471
Gamze Abakafee36392019-10-03 11:17:24 +00001472 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301473 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301474 olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301475 // return err
1476 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001477 }
Shrey Baid26912972020-04-16 21:02:31 +05301478 log.Debugw("tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001479 }
1480 return nil
1481}
1482
1483// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301484func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001485 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001486 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001487 }
npujarec5762e2020-01-01 14:08:48 +05301488 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301489 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1490 log.Fields{
1491 "tp-id": tpID,
1492 "uni-port-name": uniPortName,
1493 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001494 }
1495 return nil
1496}
1497
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001498func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301499 if len(classifier) == 0 { // should never happen
Shrey Baid26912972020-04-16 21:02:31 +05301500 logger.Error("invalid-classfier-object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301501 return 0
1502 }
Shrey Baid26912972020-04-16 21:02:31 +05301503 logger.Debugw("generating-flow-store-cookie",
1504 log.Fields{
1505 "classifier": classifier,
1506 "gemport-id": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301507 var jsonData []byte
1508 var flowString string
1509 var err error
1510 // TODO: Do we need to marshall ??
1511 if jsonData, err = json.Marshal(classifier); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301512 logger.Error("failed-to-encode-classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301513 return 0
1514 }
1515 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001516 if gemPortID != 0 {
1517 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301518 }
1519 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001520 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301521 hash := big.NewInt(0)
1522 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301523 generatedHash := hash.Uint64()
Shrey Baid26912972020-04-16 21:02:31 +05301524 logger.Debugw("hash-generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301525 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301526}
1527
npujarec5762e2020-01-01 14:08:48 +05301528func (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 +05301529 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001530 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001531 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1532 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1533 */
1534 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001535 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001536 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001537 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001538 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001539 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301540 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001541 if existingFlows != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301542 logger.Debugw("flow-exists-for-given-flowID--appending-it-to-current-flow",
1543 log.Fields{
1544 "flow-id": flow.FlowId,
1545 "device-id": f.deviceHandler.device.Id,
1546 "intf-id": intfID,
1547 "onu-id": flow.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001548 //for _, f := range *existingFlows {
1549 // flows = append(flows, f)
1550 //}
1551 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001552 }
Shrey Baid26912972020-04-16 21:02:31 +05301553 logger.Debugw("updated-flows-for-given-flowID-and-onuid",
1554 log.Fields{
1555 "updatedflow": flows,
1556 "flow-id": flow.FlowId,
1557 "onu-id": flow.OnuId,
1558 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +05301559 return &flows
1560}
1561
npujarec5762e2020-01-01 14:08:48 +05301562func (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 +05301563 logger.Debugw("storing-flow(s)-into-kv-store", log.Fields{
1564 "flow-id": flowID,
1565 "device-id": f.deviceHandler.device.Id,
1566 "intf-id": intfID,
1567 "onu-id": onuID})
npujarec5762e2020-01-01 14:08:48 +05301568 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301569 logger.Warnw("error-while-storing-flow-into-kv-store", log.Fields{
1570 "device-id": f.deviceHandler.device.Id,
1571 "onu-id": onuID,
1572 "intf-id": intfID,
1573 "flow-id": flowID})
manikkaraj k17652a72019-05-06 09:06:36 -04001574 return err
1575 }
Shrey Baid26912972020-04-16 21:02:31 +05301576 logger.Infow("stored-flow(s)-into-kv-store-successfully!", log.Fields{
1577 "device-id": f.deviceHandler.device.Id,
1578 "onu-id": onuID,
1579 "intf-id": intfID,
1580 "flow-id": flowID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301581 return nil
1582}
1583
David K. Bainbridge794735f2020-02-11 21:01:37 -08001584func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001585
1586 var intfID uint32
1587 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1588 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1589 */
1590 if deviceFlow.AccessIntfId != -1 {
1591 intfID = uint32(deviceFlow.AccessIntfId)
1592 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001593 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001594 intfID = uint32(deviceFlow.NetworkIntfId)
1595 }
1596
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001597 logger.Debugw("sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301598 "flow": *deviceFlow,
1599 "device-id": f.deviceHandler.device.Id,
1600 "intf-id": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301601 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001602
1603 st, _ := status.FromError(err)
1604 if st.Code() == codes.AlreadyExists {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001605 logger.Debug("flow-already-exists", log.Fields{
1606 "err": err,
1607 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301608 "device-id": f.deviceHandler.device.Id,
1609 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001610 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301611 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001612
1613 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301614 logger.Errorw("failed-to-add-flow-to-device",
1615 log.Fields{"err": err,
1616 "device-flow": deviceFlow,
1617 "device-id": f.deviceHandler.device.Id,
1618 "intf-id": intfID})
npujarec5762e2020-01-01 14:08:48 +05301619 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001620 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001621 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301622 if deviceFlow.GemportId != -1 {
1623 // No need to register the flow if it is a trap on nni flow.
npujarec5762e2020-01-01 14:08:48 +05301624 f.registerFlow(ctx, logicalFlow, deviceFlow)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301625 }
Shrey Baid26912972020-04-16 21:02:31 +05301626 logger.Infow("flow-added-to-device-successfully ",
1627 log.Fields{
1628 "flow": *deviceFlow,
1629 "device-id": f.deviceHandler.device.Id,
1630 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001631 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001632}
1633
Matteo Scandolo92186242020-06-12 10:54:18 -07001634func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
Shrey Baid26912972020-04-16 21:02:31 +05301635 logger.Debugw("sending-flow-to-device-via-grpc",
1636 log.Fields{
1637 "flow": *deviceFlow,
1638 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001639 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1640 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001641 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Shrey Baid26912972020-04-16 21:02:31 +05301642 logger.Warnw("can-not-remove-flow-from-device--unreachable",
1643 log.Fields{
1644 "err": err,
1645 "deviceFlow": deviceFlow,
1646 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001647 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001648 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001649 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001650 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001651
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001652 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001653 logger.Infow("flow-removed-from-device-successfully", log.Fields{
1654 "of-flow-id": ofFlowID,
1655 "flow": *deviceFlow,
1656 "device-id": f.deviceHandler.device.Id,
1657 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001658 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301659}
1660
David K. Bainbridge794735f2020-02-11 21:01:37 -08001661func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001662
1663 classifierInfo := make(map[string]interface{})
1664 actionInfo := make(map[string]interface{})
1665
1666 classifierInfo[EthType] = uint32(LldpEthType)
1667 classifierInfo[PacketTagType] = Untagged
1668 actionInfo[TrapToHost] = true
1669
1670 // LLDP flow is installed to trap LLDP packets on the NNI port.
1671 // We manage flow_id resource pool on per PON port basis.
1672 // Since this situation is tricky, as a hack, we pass the NNI port
1673 // index (network_intf_id) as PON port Index for the flow_id resource
1674 // pool. Also, there is no ONU Id available for trapping LLDP packets
1675 // on NNI port, use onu_id as -1 (invalid)
1676 // ****************** CAVEAT *******************
1677 // This logic works if the NNI Port Id falls within the same valid
1678 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1679 // we need to have a re-look at this.
1680 // *********************************************
1681
1682 var onuID = -1
1683 var uniID = -1
1684 var gemPortID = -1
1685
David K. Bainbridge794735f2020-02-11 21:01:37 -08001686 networkInterfaceID, err := IntfIDFromNniPortNum(portNo)
1687 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301688 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001689 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001690 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301691 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301692 logger.Infow("flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001693 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001694 }
npujarec5762e2020-01-01 14:08:48 +05301695 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001696
1697 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301698 return olterrors.NewErrNotFound("flow-id",
1699 log.Fields{
1700 "interface-id": networkInterfaceID,
1701 "onu-id": onuID,
1702 "uni-id": uniID,
1703 "gem-port-id": gemPortID,
1704 "cookie": flowStoreCookie,
1705 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001706 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001707 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001708 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1709 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301710 return olterrors.NewErrInvalidValue(
1711 log.Fields{
1712 "classifier": classifierInfo,
1713 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001714 }
Shrey Baid26912972020-04-16 21:02:31 +05301715 logger.Debugw("created-classifier-proto",
1716 log.Fields{
1717 "classifier": *classifierProto,
1718 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001719 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001720 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301721 return olterrors.NewErrInvalidValue(
1722 log.Fields{
1723 "action": actionInfo,
1724 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001725 }
Shrey Baid26912972020-04-16 21:02:31 +05301726 logger.Debugw("created-action-proto",
1727 log.Fields{
1728 "action": *actionProto,
1729 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001730
1731 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1732 OnuId: int32(onuID), // OnuId not required
1733 UniId: int32(uniID), // UniId not used
1734 FlowId: flowID,
1735 FlowType: Downstream,
1736 NetworkIntfId: int32(networkInterfaceID),
1737 GemportId: int32(gemPortID),
1738 Classifier: classifierProto,
1739 Action: actionProto,
1740 Priority: int32(flow.Priority),
1741 Cookie: flow.Cookie,
1742 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001743 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301744 return olterrors.NewErrFlowOp("add", flowID,
1745 log.Fields{
1746 "flow": downstreamflow,
1747 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001748 }
Shrey Baid26912972020-04-16 21:02:31 +05301749 logger.Infow("lldp-trap-on-nni-flow-added-to-device-successfully",
1750 log.Fields{
1751 "device-id": f.deviceHandler.device.Id,
1752 "onu-id": onuID,
1753 "flow-id": flowID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001754 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1755 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1756 int32(onuID),
1757 int32(uniID),
1758 flowID, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301759 return olterrors.NewErrPersistence("update", "flow", flowID,
1760 log.Fields{
1761 "flow": downstreamflow,
1762 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001763 }
1764 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301765}
1766
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001767func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1768 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001769}
1770
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001771//getOnuDevice to fetch onu from cache or core.
1772func (f *OpenOltFlowMgr) getOnuDevice(intfID uint32, onuID uint32) (*OnuDevice, error) {
1773 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1774 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1775 if !ok {
Shrey Baid26912972020-04-16 21:02:31 +05301776 logger.Debugw("couldnt-find-onu-in-cache",
1777 log.Fields{
1778 "intf-id": intfID,
1779 "onu-id": onuID,
1780 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001781 onuDevice, err := f.getChildDevice(intfID, onuID)
1782 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301783 return nil, olterrors.NewErrNotFound("onu-child-device",
1784 log.Fields{
1785 "onu-id": onuID,
1786 "intf-id": intfID,
1787 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001788 }
1789 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1790 //better to ad the device to cache here.
1791 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1792 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301793 logger.Debugw("found-onu-in-cache",
1794 log.Fields{
1795 "intf-id": intfID,
1796 "onu-id": onuID,
1797 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001798 }
1799
1800 return onuDev.(*OnuDevice), nil
1801}
1802
1803//getChildDevice to fetch onu
1804func (f *OpenOltFlowMgr) getChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
Shrey Baid26912972020-04-16 21:02:31 +05301805 logger.Infow("GetChildDevice",
1806 log.Fields{
1807 "pon-port": intfID,
1808 "onu-id": onuID,
1809 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001810 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001811 onuDevice, err := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
1812 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301813 return nil, olterrors.NewErrNotFound("onu",
1814 log.Fields{
1815 "interface-id": parentPortNo,
1816 "onu-id": onuID,
1817 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001818 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301819 }
Shrey Baid26912972020-04-16 21:02:31 +05301820 logger.Infow("successfully-received-child-device-from-core",
1821 log.Fields{
1822 "device-id": f.deviceHandler.device.Id,
1823 "child_device_id": onuDevice.Id,
1824 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301825 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301826}
1827
1828func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Shrey Baid26912972020-04-16 21:02:31 +05301829 logger.Info("unimplemented-flow %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301830 return nil
1831}
1832
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001833func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
Shrey Baid26912972020-04-16 21:02:31 +05301834 logger.Info("unimplemented-device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301835}
1836
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001837func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001838 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001839 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001840 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001841 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001842}
1843
Girish Gowdra6b130582019-11-20 16:45:20 +05301844func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001845 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301846 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301847 logger.Debugw("couldnt-find-onu-child-device",
1848 log.Fields{
1849 "intf-id": intfID,
1850 "onu-id": onuID,
1851 "uni-id": uniID,
1852 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001853 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301854 }
1855
1856 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Shrey Baid26912972020-04-16 21:02:31 +05301857 logger.Debugw("sending-gem-port-delete-to-openonu-adapter",
1858 log.Fields{
1859 "msg": *delGemPortMsg,
1860 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301861 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1862 delGemPortMsg,
1863 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301864 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001865 onuDev.deviceType,
1866 onuDev.deviceID,
1867 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301868 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1869 log.Fields{
1870 "from-adapter": f.deviceHandler.device.Type,
1871 "to-adapter": onuDev.deviceType,
1872 "onu-id": onuDev.deviceID,
1873 "proxyDeviceID": onuDev.proxyDeviceID,
1874 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301875 }
Shrey Baid26912972020-04-16 21:02:31 +05301876 logger.Infow("success-sending-del-gem-port-to-onu-adapter",
1877 log.Fields{
1878 "msg": delGemPortMsg,
1879 "from-adapter": f.deviceHandler.device.Type,
1880 "to-adapter": onuDev.deviceType,
1881 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301882 return nil
1883}
1884
1885func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001886 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301887 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301888 logger.Warnw("couldnt-find-onu-child-device",
1889 log.Fields{
1890 "intf-id": intfID,
1891 "onu-id": onuID,
1892 "uni-id": uniID,
1893 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001894 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301895 }
1896
1897 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Shrey Baid26912972020-04-16 21:02:31 +05301898 logger.Debugw("sending-tcont-delete-to-openonu-adapter",
1899 log.Fields{
1900 "msg": *delTcontMsg,
1901 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301902 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1903 delTcontMsg,
1904 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301905 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001906 onuDev.deviceType,
1907 onuDev.deviceID,
1908 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301909 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1910 log.Fields{
1911 "from-adapter": f.deviceHandler.device.Type,
1912 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1913 "proxyDeviceID": onuDev.proxyDeviceID,
1914 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301915 }
Shrey Baid26912972020-04-16 21:02:31 +05301916 logger.Infow("success-sending-del-tcont-to-onu-adapter",
1917 log.Fields{
1918 "msg": delTcontMsg,
1919 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301920 return nil
1921}
1922
Girish Gowdra3d633032019-12-10 16:37:05 +05301923func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1924 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1925 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1926 if val.(int) > 0 {
1927 pnFlDels := val.(int) - 1
1928 if pnFlDels > 0 {
Shrey Baid26912972020-04-16 21:02:31 +05301929 logger.Debugw("flow-delete-succeeded--more-pending",
1930 log.Fields{
1931 "intf": Intf,
1932 "onu-id": onuID,
1933 "uni-id": uniID,
1934 "currpendingflowcnt": pnFlDels,
1935 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301936 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1937 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301938 logger.Debugw("all-pending-flow-deletes-handled--removing-entry-from-map",
1939 log.Fields{
1940 "intf": Intf,
1941 "onu-id": onuID,
1942 "uni-id": uniID,
1943 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301944 f.pendingFlowDelete.Delete(pnFlDelKey)
1945 }
1946 }
1947 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301948 logger.Debugw("no-pending-delete-flows-found",
1949 log.Fields{
1950 "intf": Intf,
1951 "onu-id": onuID,
1952 "uni-id": uniID,
1953 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301954
1955 }
1956
1957}
1958
Girish Gowdrac3037402020-01-22 20:29:53 +05301959// Once the gemport is released for a given onu, it also has to be cleared from local cache
1960// which was used for deriving the gemport->logicalPortNo during packet-in.
1961// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1962// is conveyed to ONOS during packet-in OF message.
1963func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001964
Matteo Scandolo60913ed2020-06-23 19:31:14 -07001965 f.onuGemInfoLock.Lock()
1966 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001967
Shrey Baid26912972020-04-16 21:02:31 +05301968 logger.Infow("deleting-gem-from-local-cache",
1969 log.Fields{
Matteo Scandolo60913ed2020-06-23 19:31:14 -07001970 "gem-port-id": gemPortID,
1971 "intf-id": intfID,
1972 "onu-id": onuID,
1973 "device-id": f.deviceHandler.device.Id,
1974 "onu-gem": f.onuGemInfo[intfID]})
Girish Gowdrac3037402020-01-22 20:29:53 +05301975 onugem := f.onuGemInfo[intfID]
Matteo Scandolo60913ed2020-06-23 19:31:14 -07001976deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001977 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301978 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001979 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301980 // If the gemport is found, delete it from local cache.
1981 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001982 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1983 onugem[i] = onu
Shrey Baid26912972020-04-16 21:02:31 +05301984 logger.Infow("removed-gemport-from-local-cache",
1985 log.Fields{
1986 "intf-id": intfID,
1987 "onu-id": onuID,
1988 "deletedgemport-id": gemPortID,
1989 "gemports": onu.GemPorts,
1990 "device-id": f.deviceHandler.device.Id})
Matteo Scandolo60913ed2020-06-23 19:31:14 -07001991 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301992 }
1993 }
Matteo Scandolo60913ed2020-06-23 19:31:14 -07001994 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301995 }
1996 }
1997}
1998
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301999//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002000// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302001func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302002 gemPortID int32, flowID uint32, flowDirection string,
2003 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002004
Chaitrashree G S90a17952019-11-14 21:51:21 -05002005 tpID, err := getTpIDFromFlow(flow)
2006 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302007 return olterrors.NewErrNotFound("tp-id",
2008 log.Fields{
2009 "flow": flow,
2010 "intf": Intf,
2011 "onu-id": onuID,
2012 "uni-id": uniID,
2013 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002014 }
Gamze Abakafee36392019-10-03 11:17:24 +00002015
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002016 if len(updatedFlows) >= 0 {
2017 // There are still flows referencing the same flow_id.
2018 // So the flow should not be freed yet.
2019 // For ex: Case of HSIA where same flow is shared
2020 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00002021 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302022 olterrors.NewErrPersistence("update", "flow", flowID,
2023 log.Fields{
2024 "flow": updatedFlows,
2025 "device-id": f.deviceHandler.device.Id}, err).Log()
Girish Kumarf26e4882020-03-05 06:49:10 +00002026 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002027 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05302028 // Do this for subscriber flows only (not trap from NNI flows)
2029 if onuID != -1 && uniID != -1 {
2030 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
2031 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Shrey Baid26912972020-04-16 21:02:31 +05302032 logger.Debugw("creating-entry-for-pending-flow-delete",
2033 log.Fields{
2034 "flow-id": flowID,
2035 "intf": Intf,
2036 "onu-id": onuID,
2037 "uni-id": uniID,
2038 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302039 f.pendingFlowDelete.Store(pnFlDelKey, 1)
2040 } else {
2041 pnFlDels := val.(int) + 1
Shrey Baid26912972020-04-16 21:02:31 +05302042 logger.Debugw("updating-flow-delete-entry",
2043 log.Fields{
2044 "flow-id": flowID,
2045 "intf": Intf,
2046 "onu-id": onuID,
2047 "uni-id": uniID,
2048 "currPendingFlowCnt": pnFlDels,
2049 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302050 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
2051 }
2052
2053 defer f.deletePendingFlows(Intf, onuID, uniID)
2054 }
2055
Shrey Baid26912972020-04-16 21:02:31 +05302056 logger.Debugw("releasing-flow-id-to-resource-manager",
2057 log.Fields{
2058 "Intf": Intf,
2059 "onu-id": onuID,
2060 "uni-id": uniID,
2061 "flow-id": flowID,
2062 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302063 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002064
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002065 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302066 tpPath := f.getTPpath(Intf, uni, tpID)
Shrey Baid26912972020-04-16 21:02:31 +05302067 logger.Debugw("getting-techprofile-instance-for-subscriber",
2068 log.Fields{
2069 "TP-PATH": tpPath,
2070 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302071 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00002072 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +05302073 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
2074 log.Fields{
2075 "tp-id": tpID,
2076 "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002077 }
2078
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302079 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00002080 if f.isGemPortUsedByAnotherFlow(gemPK) {
2081 flowIDs := f.flowsUsedByGemPort[gemPK]
2082 for i, flowIDinMap := range flowIDs {
2083 if flowIDinMap == flowID {
2084 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302085 // everytime flowsUsedByGemPort cache is updated the same should be updated
2086 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002087 f.flowsUsedByGemPort[gemPK] = flowIDs
npujarec5762e2020-01-01 14:08:48 +05302088 f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00002089 break
2090 }
2091 }
Shrey Baid26912972020-04-16 21:02:31 +05302092 logger.Debugw("gem-port-id-is-still-used-by-other-flows",
2093 log.Fields{
2094 "gemport-id": gemPortID,
2095 "usedByFlows": flowIDs,
2096 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302097 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00002098 }
Shrey Baid26912972020-04-16 21:02:31 +05302099 logger.Debugf("gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05302100 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002101 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
2102 // 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 +05302103 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Girish Gowdrac3037402020-01-22 20:29:53 +05302104 f.deleteGemPortFromLocalCache(Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002105 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302106 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
2107 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002108 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05302109 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
2110 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002111 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05302112 // Delete the gem port on the ONU.
2113 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302114 logger.Errorw("error-processing-delete-gem-port-towards-onu",
2115 log.Fields{
2116 "err": err,
2117 "intf": Intf,
2118 "onu-id": onuID,
2119 "uni-id": uniID,
2120 "device-id": f.deviceHandler.device.Id,
2121 "gemport-id": gemPortID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302122 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002123 switch techprofileInst := techprofileInst.(type) {
2124 case *tp.TechProfile:
2125 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
2126 if !ok {
2127 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
2128 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
2129 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
2130 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
2131 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
2132 // Delete the TCONT on the ONU.
2133 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
2134 logger.Errorw("error-processing-delete-tcont-towards-onu",
2135 log.Fields{
2136 "intf": Intf,
2137 "onu-id": onuID,
2138 "uni-id": uniID,
2139 "device-id": f.deviceHandler.device.Id,
2140 "alloc-id": techprofileInst.UsScheduler.AllocID})
2141 }
2142 }
2143 case *tp.EponProfile:
npujarec5762e2020-01-01 14:08:48 +05302144 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
npujarec5762e2020-01-01 14:08:48 +05302145 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002146 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302147 // Delete the TCONT on the ONU.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002148 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.AllocID), tpPath); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302149 logger.Errorw("error-processing-delete-tcont-towards-onu",
2150 log.Fields{
2151 "intf": Intf,
2152 "onu-id": onuID,
2153 "uni-id": uniID,
2154 "device-id": f.deviceHandler.device.Id,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002155 "alloc-id": techprofileInst.AllocID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302156 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002157 default:
2158 logger.Errorw("error-unknown-tech",
2159 log.Fields{
2160 "techprofileInst": techprofileInst})
Gamze Abakafee36392019-10-03 11:17:24 +00002161 }
2162 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002163 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302164 return nil
2165}
2166
David K. Bainbridge794735f2020-02-11 21:01:37 -08002167// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302168func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302169
Shrey Baid26912972020-04-16 21:02:31 +05302170 logger.Infow("clear-flow-from-resource-manager",
2171 log.Fields{
2172 "flowDirection": flowDirection,
2173 "flow": *flow,
2174 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002175
2176 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05302177 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002178 return
2179 }
2180
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302181 var updatedFlows []rsrcMgr.FlowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302182 classifierInfo := make(map[string]interface{})
2183
2184 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
2185 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002186 logger.Error(err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302187 return
2188 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302189
David K. Bainbridge794735f2020-02-11 21:01:37 -08002190 onuID := int32(onu)
2191 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302192
2193 for _, field := range flows.GetOfbFields(flow) {
2194 if field.Type == flows.IP_PROTO {
2195 classifierInfo[IPProto] = field.GetIpProto()
Shrey Baid26912972020-04-16 21:02:31 +05302196 logger.Debugw("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302197 }
2198 }
Shrey Baid26912972020-04-16 21:02:31 +05302199 logger.Infow("extracted-access-info-from-flow-to-be-deleted",
2200 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002201 "flow-id": flow.Id,
2202 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302203 "onu-id": onuID,
2204 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302205
2206 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2207 onuID = -1
2208 uniID = -1
Shrey Baid26912972020-04-16 21:02:31 +05302209 logger.Debug("trap-on-nni-flow-set-oni--uni-to- -1")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002210 Intf, err = IntfIDFromNniPortNum(inPort)
2211 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002212 logger.Errorw("invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002213 log.Fields{
2214 "port-number": inPort,
2215 "error": err})
2216 return
2217 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302218 }
npujarec5762e2020-01-01 14:08:48 +05302219 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002220 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302221 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302222 if flowInfo == nil {
Shrey Baid26912972020-04-16 21:02:31 +05302223 logger.Debugw("no-flowinfo-found-in-kv-store",
2224 log.Fields{
2225 "intf": Intf,
2226 "onu-id": onuID,
2227 "uni-id": uniID,
2228 "flow-id": flowID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302229 return
2230 }
2231 updatedFlows = nil
2232 for _, flow := range *flowInfo {
2233 updatedFlows = append(updatedFlows, flow)
2234 }
2235
2236 for i, storedFlow := range updatedFlows {
2237 if flow.Id == storedFlow.LogicalFlowID {
2238 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Shrey Baid26912972020-04-16 21:02:31 +05302239 logger.Debugw("flow-to-be-deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002240 // DKB
Matteo Scandolo92186242020-06-12 10:54:18 -07002241 if err = f.removeFlowFromDevice(&removeFlowMessage, flow.Id); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002242 logger.Errorw("failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002243 return
2244 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002245 logger.Info("flow-removed-from-device-successfully", log.Fields{
2246 "flow-id": flow.Id,
2247 "stored-flow": storedFlow,
2248 "device-id": f.deviceHandler.device.Id,
2249 "stored-flow-id": flowID,
2250 "onu-id": onuID,
2251 "intf": Intf,
2252 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08002253 //Remove the Flow from FlowInfo
2254 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
2255 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
2256 flowID, flowDirection, portNum, updatedFlows); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07002257 logger.Error("failed-to-clear-resources-for-flow", log.Fields{
2258 "flow-id": flow.Id,
2259 "stored-flow": storedFlow,
2260 "device-id": f.deviceHandler.device.Id,
2261 "stored-flow-id": flowID,
2262 "onu-id": onuID,
2263 "intf": Intf,
2264 })
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302265 return
2266 }
2267 }
2268 }
2269 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002270}
2271
Esin Karamanccb714b2019-11-29 15:02:06 +00002272//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
2273// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05302274func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002275 classifierInfo := make(map[string]interface{})
2276 formulateClassifierInfoFromFlow(classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00002277 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002278
2279 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302280 logger.Warnw("no-inport-found--cannot-release-resources-of-the-multicast-flow", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002281 return
2282 }
2283
Esin Karamanccb714b2019-11-29 15:02:06 +00002284 var onuID = int32(NoneOnuID)
2285 var uniID = int32(NoneUniID)
2286 var flowID uint32
2287 var updatedFlows []rsrcMgr.FlowInfo
2288
npujarec5762e2020-01-01 14:08:48 +05302289 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002290
2291 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302292 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002293 if flowInfo == nil {
Shrey Baid26912972020-04-16 21:02:31 +05302294 logger.Debugw("no-multicast-flowinfo-found-in-the-kv-store",
2295 log.Fields{
2296 "intf": networkInterfaceID,
2297 "onu-id": onuID,
2298 "uni-id": uniID,
2299 "flow-id": flowID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002300 continue
2301 }
2302 updatedFlows = nil
2303 for _, flow := range *flowInfo {
2304 updatedFlows = append(updatedFlows, flow)
2305 }
2306 for i, storedFlow := range updatedFlows {
2307 if flow.Id == storedFlow.LogicalFlowID {
2308 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Shrey Baid26912972020-04-16 21:02:31 +05302309 logger.Debugw("multicast-flow-to-be-deleted",
2310 log.Fields{
2311 "flow": storedFlow,
2312 "flow-id": flow.Id,
2313 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002314 //remove from device
Matteo Scandolo92186242020-06-12 10:54:18 -07002315 if err := f.removeFlowFromDevice(&removeFlowMessage, flow.Id); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002316 // DKB
Girish Kumar2ad402b2020-03-20 19:45:12 +00002317 logger.Errorw("failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002318 log.Fields{
2319 "flow-id": flow.Id,
2320 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002321 return
2322 }
Shrey Baid26912972020-04-16 21:02:31 +05302323 logger.Infow("multicast-flow-removed-from-device-successfully", log.Fields{"flow-id": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002324 //Remove the Flow from FlowInfo
2325 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05302326 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302327 logger.Errorw("failed-to-delete-multicast-flow-from-the-kv-store",
2328 log.Fields{"flow": storedFlow,
2329 "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002330 return
2331 }
2332 //release flow id
Shrey Baid26912972020-04-16 21:02:31 +05302333 logger.Debugw("releasing-multicast-flow-id",
2334 log.Fields{"flow-id": flowID,
2335 "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05302336 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002337 }
2338 }
2339 }
2340}
2341
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002342//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002343func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002344 logger.Infow("removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302345 var direction string
2346 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002347
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302348 for _, action := range flows.GetActions(flow) {
2349 if action.Type == flows.OUTPUT {
2350 if out := action.GetOutput(); out != nil {
2351 actionInfo[Output] = out.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002352 logger.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302353 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302354 logger.Error("invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002355 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002356 }
2357 }
2358 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002359
2360 if flows.HasGroup(flow) {
2361 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07002362 f.clearFlowFromResourceManager(ctx, flow, direction)
2363 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002364 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302365 direction = Upstream
2366 } else {
2367 direction = Downstream
2368 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302369
Girish Gowdracefae192020-03-19 18:14:10 -07002370 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(flow, direction)
2371 if err != nil {
2372 return err
2373 }
2374
2375 userKey := tpLockKey{intfID, onuID, uniID}
2376
2377 // Serialize flow removes on a per subscriber basis
2378 if f.perUserFlowHandleLock.TryLock(userKey) {
2379 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
2380 f.perUserFlowHandleLock.Unlock(userKey)
2381 } else {
2382 // Ideally this should never happen
Shrey Baid26912972020-04-16 21:02:31 +05302383 logger.Errorw("failed-to-acquire-lock-to-remove-flow--remove-aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07002384 return errors.New("failed-to-acquire-per-user-lock")
2385 }
2386
2387 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002388}
2389
Girish Gowdra3d633032019-12-10 16:37:05 +05302390func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
2391 uniID uint32, ch chan bool) {
2392 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2393 for {
2394 select {
2395 case <-time.After(20 * time.Millisecond):
2396 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Shrey Baid26912972020-04-16 21:02:31 +05302397 logger.Debug("pending-flow-deletes-completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05302398 ch <- true
2399 return
2400 }
2401 case <-ctx.Done():
Shrey Baid26912972020-04-16 21:02:31 +05302402 logger.Error("flow-delete-wait-handler-routine-canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05302403 return
2404 }
2405 }
2406}
2407
Esin Karamanae41e2b2019-12-17 18:13:13 +00002408//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2409func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2410 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2411 if ethType, ok := classifierInfo[EthType]; ok {
2412 if ethType.(uint32) == IPv4EthType {
2413 if ipProto, ok := classifierInfo[IPProto]; ok {
2414 if ipProto.(uint32) == IgmpProto {
2415 return true
2416 }
2417 }
2418 }
2419 }
2420 }
2421 return false
2422}
2423
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002424// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302425// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002426func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002427 classifierInfo := make(map[string]interface{})
2428 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002429 var UsMeterID uint32
2430 var DsMeterID uint32
2431
Shrey Baid26912972020-04-16 21:02:31 +05302432 logger.Infow("adding-flow",
2433 log.Fields{
2434 "flow": flow,
2435 "flowmetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002436 formulateClassifierInfoFromFlow(classifierInfo, flow)
2437
2438 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
2439 if err != nil {
2440 // Error logging is already done in the called function
2441 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002442 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302443 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002444
Esin Karamanccb714b2019-11-29 15:02:06 +00002445 if flows.HasGroup(flow) {
2446 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002447 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002448 }
2449
manikkaraj k17652a72019-05-06 09:06:36 -04002450 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00002451 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
2452 if err != nil {
2453 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002454 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002455 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002456
Shrey Baid26912972020-04-16 21:02:31 +05302457 logger.Debugw("flow-ports",
2458 log.Fields{
2459 "classifierinfo_inport": classifierInfo[InPort],
2460 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002461 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002462
Humera Kouser94d7a842019-08-25 19:04:32 -04002463 if ethType, ok := classifierInfo[EthType]; ok {
2464 if ethType.(uint32) == LldpEthType {
Shrey Baid26912972020-04-16 21:02:31 +05302465 logger.Info("adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002466 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002467 }
2468 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002469 if ipProto, ok := classifierInfo[IPProto]; ok {
2470 if ipProto.(uint32) == IPProtoDhcp {
2471 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302472 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002473 logger.Debug("trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002474 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002475 }
2476 }
2477 }
2478 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002479 if isIgmpTrapDownstreamFlow(classifierInfo) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002480 logger.Debug("trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002481 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002482 }
A R Karthick1f85b802019-10-11 05:06:05 +00002483
2484 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
npujarec5762e2020-01-01 14:08:48 +05302485 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002486
Chaitrashree G S90a17952019-11-14 21:51:21 -05002487 TpID, err := getTpIDFromFlow(flow)
2488 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302489 return olterrors.NewErrNotFound("tpid-for-flow",
2490 log.Fields{
2491 "flow": flow,
2492 "intf-id": IntfID,
2493 "onu-id": onuID,
2494 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002495 }
Shrey Baid26912972020-04-16 21:02:31 +05302496 logger.Debugw("tpid-for-this-subcriber",
2497 log.Fields{
2498 "tp-id": TpID,
2499 "intf-id": intfID,
2500 "onu-id": onuID,
2501 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002502 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002503 UsMeterID = flows.GetMeterIdFromFlow(flow)
Shrey Baid26912972020-04-16 21:02:31 +05302504 logger.Debugw("upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002505 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002506 DsMeterID = flows.GetMeterIdFromFlow(flow)
Shrey Baid26912972020-04-16 21:02:31 +05302507 logger.Debugw("downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002508
2509 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302510
2511 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2512 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Shrey Baid26912972020-04-16 21:02:31 +05302513 logger.Debugw("no-pending-flows-found--going-ahead-with-flow-install",
2514 log.Fields{
2515 "intf-id": intfID,
2516 "onu-id": onuID,
2517 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302518 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302519 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05302520 pendingFlowDelComplete := make(chan bool)
2521 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
2522 select {
2523 case <-pendingFlowDelComplete:
Shrey Baid26912972020-04-16 21:02:31 +05302524 logger.Debugw("all-pending-flow-deletes-completed",
2525 log.Fields{
2526 "intf-id": intfID,
2527 "onu-id": onuID,
2528 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302529 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302530
2531 case <-time.After(10 * time.Second):
Shrey Baid26912972020-04-16 21:02:31 +05302532 return olterrors.NewErrTimeout("pending-flow-deletes",
2533 log.Fields{
2534 "intf-id": intfID,
2535 "onu-id": onuID,
2536 "uni-id": uniID}, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +05302537 }
2538 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002539 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002540}
2541
Esin Karamanccb714b2019-11-29 15:02:06 +00002542// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002543func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002544 classifierInfo[PacketTagType] = DoubleTag
Shrey Baid26912972020-04-16 21:02:31 +05302545 logger.Debugw("add-multicast-flow", log.Fields{
2546 "classifier-info": classifierInfo,
2547 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002548
Esin Karaman65409d82020-03-18 10:58:18 +00002549 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002550 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002551 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002552 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002553 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
2554 //otherwise, classification is based on ipv4_dst by default.
2555 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
2556 mcastFlowClassificationByEthDst := false
2557
2558 if mcastFlowClassificationByEthDst {
2559 //replace ipDst with ethDst
2560 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
2561 flows.IsMulticastIp(ipv4Dst.(uint32)) {
2562 // replace ipv4_dst classifier with eth_dst
2563 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
2564 delete(classifierInfo, Ipv4Dst)
2565 classifierInfo[EthDst] = multicastMac
Shrey Baid26912972020-04-16 21:02:31 +05302566 logger.Debugw("multicast-ip-to-mac-conversion-success",
2567 log.Fields{
2568 "ip:": ipv4Dst.(uint32),
2569 "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002570 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002571 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002572 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002573
David K. Bainbridge794735f2020-02-11 21:01:37 -08002574 onuID := NoneOnuID
2575 uniID := NoneUniID
2576 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00002577
David K. Bainbridge794735f2020-02-11 21:01:37 -08002578 flowStoreCookie := getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302579 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05302580 logger.Infow("multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002581 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002582 }
npujarec5762e2020-01-01 14:08:48 +05302583 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00002584 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302585 return olterrors.NewErrNotFound("multicast-flow-id",
2586 log.Fields{
2587 "interface-id": networkInterfaceID,
2588 "onu-id": onuID,
2589 "uni-id": uniID,
2590 "gem-port-id": gemPortID,
2591 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002592 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002593 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002594 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2595 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002596 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002597 }
2598 groupID := actionInfo[GroupID].(uint32)
2599 multicastFlow := openoltpb2.Flow{
2600 FlowId: flowID,
2601 FlowType: Multicast,
2602 NetworkIntfId: int32(networkInterfaceID),
2603 GroupId: groupID,
2604 Classifier: classifierProto,
2605 Priority: int32(flow.Priority),
2606 Cookie: flow.Cookie}
2607
David K. Bainbridge794735f2020-02-11 21:01:37 -08002608 if err = f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002609 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002610 }
Shrey Baid26912972020-04-16 21:02:31 +05302611 logger.Info("multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002612 //get cached group
2613 group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true)
2614 if err == nil {
2615 //calling groupAdd to set group members after multicast flow creation
Andrea Campanellac63bba92020-03-10 17:01:04 +01002616 if err = f.ModifyGroup(ctx, group); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002617 //cached group can be removed now
2618 f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002619 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002620 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002621 }
2622 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002623
2624 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2625 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2626 int32(onuID),
2627 int32(uniID),
2628 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002629 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002630 }
2631 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002632}
2633
Esin Karaman65409d82020-03-18 10:58:18 +00002634//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2635func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2636 if inPort, ok := classifierInfo[InPort]; ok {
2637 nniInterfaceID, err := IntfIDFromNniPortNum(inPort.(uint32))
2638 if err != nil {
2639 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2640 }
2641 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002642 }
Esin Karaman65409d82020-03-18 10:58:18 +00002643 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302644 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002645 if e == nil && len(nniPorts) > 0 {
2646 return nniPorts[0], nil
2647 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302648 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002649}
2650
2651// AddGroup add or update the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002652func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002653 logger.Infow("add-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002654 if group == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002655 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002656 }
2657
2658 groupToOlt := openoltpb2.Group{
2659 GroupId: group.Desc.GroupId,
2660 Command: openoltpb2.Group_SET_MEMBERS,
2661 Action: f.buildGroupAction(),
2662 }
2663
Shrey Baid26912972020-04-16 21:02:31 +05302664 logger.Debugw("sending-group-to-device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05302665 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002666 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002667 return olterrors.NewErrAdapter("add-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002668 }
2669 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05302670 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002671 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002672 }
Shrey Baid26912972020-04-16 21:02:31 +05302673 logger.Infow("add-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002674 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002675}
2676
2677//buildGroupAction creates and returns a group action
2678func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2679 var actionCmd openoltpb2.ActionCmd
2680 var action openoltpb2.Action
2681 action.Cmd = &actionCmd
2682 //pop outer vlan
2683 action.Cmd.RemoveOuterTag = true
2684 return &action
2685}
2686
2687// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002688func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002689 logger.Infow("modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002690 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002691 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002692 }
2693
Andrea Campanellac63bba92020-03-10 17:01:04 +01002694 newGroup := f.buildGroup(group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002695 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302696 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002697
2698 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002699 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002700 }
2701
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002702 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002703 if groupExists {
2704 // group already exists
2705 current = f.buildGroup(group.Desc.GroupId, val.Desc.GetBuckets())
Shrey Baid26912972020-04-16 21:02:31 +05302706 logger.Debugw("modify-group--group exists",
2707 log.Fields{
2708 "group on the device": val,
2709 "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002710 } else {
2711 current = f.buildGroup(group.Desc.GroupId, nil)
2712 }
2713
Shrey Baid26912972020-04-16 21:02:31 +05302714 logger.Debugw("modify-group--comparing-current-and-new",
2715 log.Fields{
2716 "group on the device": current,
2717 "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002718 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002719 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002720 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002721 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002722
Shrey Baid26912972020-04-16 21:02:31 +05302723 logger.Infow("modify-group--differences found", log.Fields{
2724 "membersToBeAdded": membersToBeAdded,
2725 "membersToBeRemoved": membersToBeRemoved,
2726 "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002727
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002728 groupToOlt := openoltpb2.Group{
2729 GroupId: group.Desc.GroupId,
2730 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002731 var errAdd, errRemoved error
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002732 if membersToBeAdded != nil && len(membersToBeAdded) > 0 {
2733 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2734 groupToOlt.Members = membersToBeAdded
2735 //execute addMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002736 errAdd = f.callGroupAddRemove(&groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002737 }
2738 if membersToBeRemoved != nil && len(membersToBeRemoved) > 0 {
2739 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2740 groupToOlt.Members = membersToBeRemoved
2741 //execute removeMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002742 errRemoved = f.callGroupAddRemove(&groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002743 }
2744
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002745 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002746 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302747 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002748 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002749 }
Shrey Baid26912972020-04-16 21:02:31 +05302750 logger.Infow("modify-group-was-success--storing-group",
2751 log.Fields{
2752 "group": group,
2753 "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002754 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302755 logger.Warnw("one-of-the-group-add/remove-operations-failed--cannot-save-group-modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002756 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002757 if errAdd != nil {
2758 return errAdd
2759 }
2760 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002761 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002762 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002763}
2764
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002765//callGroupAddRemove performs add/remove buckets operation for the indicated group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002766func (f *OpenOltFlowMgr) callGroupAddRemove(group *openoltpb2.Group) error {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002767 if err := f.performGroupOperation(group); err != nil {
2768 st, _ := status.FromError(err)
2769 //ignore already exists error code
2770 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002771 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002772 }
2773 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002774 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002775}
2776
2777//findDiff compares group members and finds members which only exists in groups2
2778func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2779 var members []*openoltpb2.GroupMember
2780 for _, bucket := range group2.Members {
2781 if !f.contains(group1.Members, bucket) {
2782 // bucket does not exist and must be added
2783 members = append(members, bucket)
2784 }
2785 }
2786 return members
2787}
2788
2789//contains returns true if the members list contains the given member; false otherwise
2790func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2791 for _, groupMember := range members {
2792 if groupMember.InterfaceId == member.InterfaceId {
2793 return true
2794 }
2795 }
2796 return false
2797}
2798
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002799//performGroupOperation call performGroupOperation operation of openolt proto
2800func (f *OpenOltFlowMgr) performGroupOperation(group *openoltpb2.Group) error {
Shrey Baid26912972020-04-16 21:02:31 +05302801 logger.Debugw("sending-group-to-device",
2802 log.Fields{
2803 "groupToOlt": group,
2804 "command": group.Command})
Esin Karamanccb714b2019-11-29 15:02:06 +00002805 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2806 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002807 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002808 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002809 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002810}
2811
2812//buildGroup build openoltpb2.Group from given group id and bucket list
2813func (f *OpenOltFlowMgr) buildGroup(groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
2814 group := openoltpb2.Group{
2815 GroupId: groupID}
2816 // create members of the group
2817 if buckets != nil {
2818 for _, ofBucket := range buckets {
2819 member := f.buildMember(ofBucket)
2820 if member != nil && !f.contains(group.Members, member) {
2821 group.Members = append(group.Members, member)
2822 }
2823 }
2824 }
2825 return &group
2826}
2827
2828//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
2829func (f *OpenOltFlowMgr) buildMember(ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
2830 var outPort uint32
2831 outPortFound := false
2832 for _, ofAction := range ofBucket.Actions {
2833 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2834 outPort = ofAction.GetOutput().Port
2835 outPortFound = true
2836 }
2837 }
2838
2839 if !outPortFound {
Shrey Baid26912972020-04-16 21:02:31 +05302840 logger.Debugw("bucket-skipped-since-no-out-port-found-in-it", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002841 return nil
2842 }
2843 interfaceID := IntfIDFromUniPortNum(outPort)
Shrey Baid26912972020-04-16 21:02:31 +05302844 logger.Debugw("got-associated-interface-id-of-the-port",
2845 log.Fields{
2846 "portNumber:": outPort,
2847 "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002848 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2849 member := openoltpb2.GroupMember{
2850 InterfaceId: interfaceID,
2851 InterfaceType: openoltpb2.GroupMember_PON,
2852 GemPortId: groupInfo.gemPortID,
2853 Priority: groupInfo.servicePriority,
2854 }
2855 //add member to the group
2856 return &member
2857 }
Shrey Baid26912972020-04-16 21:02:31 +05302858 logger.Warnf("bucket-skipped-since-interface-2-gem-mapping-cannot-be-found", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002859 return nil
2860}
2861
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002862//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04002863func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002864
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002865 onuDev, err := f.getOnuDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302866 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302867 logger.Errorw("couldnt-find-onu-child-device",
2868 log.Fields{
2869 "intf-id": intfID,
2870 "onu-id": onuID,
2871 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002872 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302873 }
Shrey Baid26912972020-04-16 21:02:31 +05302874 logger.Debugw("got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002875
Manikkaraj kb1d51442019-07-23 10:41:02 -04002876 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002877 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Matteo Scandolo92186242020-06-12 10:54:18 -07002878 logger.Debugw("sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
manikkaraj k17652a72019-05-06 09:06:36 -04002879 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2880 tpDownloadMsg,
2881 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302882 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002883 onuDev.deviceType,
2884 onuDev.deviceID,
2885 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002886 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302887 return olterrors.NewErrCommunication("send-techprofile-download-request",
2888 log.Fields{
2889 "from-adapter": f.deviceHandler.device.Type,
2890 "to-adapter": onuDev.deviceType,
2891 "onu-id": onuDev.deviceID,
2892 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002893 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002894 logger.Infow("success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302895 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302896}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002897
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302898//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002899func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302900
Matteo Scandolo60913ed2020-06-23 19:31:14 -07002901 f.onuGemInfoLock.Lock()
2902 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002903
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302904 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2905 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002906 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002907 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302908 }
Shrey Baid26912972020-04-16 21:02:31 +05302909 logger.Infow("updated-onuinfo",
2910 log.Fields{
2911 "intf-id": intfID,
2912 "onu-id": onuID,
2913 "serial-num": serialNum,
2914 "onu": onu,
2915 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002916 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002917}
2918
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302919//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302920func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002921
Matteo Scandolo60913ed2020-06-23 19:31:14 -07002922 f.onuGemInfoLock.Lock()
2923 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002924
Shrey Baid26912972020-04-16 21:02:31 +05302925 logger.Infow("adding-gem-to-onu-info-map",
2926 log.Fields{
Matteo Scandolo60913ed2020-06-23 19:31:14 -07002927 "gem-port-id": gemPort,
2928 "intf-id": intfID,
2929 "onu-id": onuID,
2930 "device-id": f.deviceHandler.device.Id,
2931 "onu-gem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302932 onugem := f.onuGemInfo[intfID]
2933 // update the gem to the local cache as well as to kv strore
2934 for idx, onu := range onugem {
2935 if onu.OnuID == onuID {
2936 // check if gem already exists , else update the cache and kvstore
2937 for _, gem := range onu.GemPorts {
2938 if gem == gemPort {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002939 logger.Debugw("gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302940 log.Fields{
2941 "gem": gemPort,
2942 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302943 return
2944 }
2945 }
2946 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2947 f.onuGemInfo[intfID] = onugem
2948 }
2949 }
npujarec5762e2020-01-01 14:08:48 +05302950 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302951 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302952 logger.Errorw("failed-to-add-gem-to-onu",
2953 log.Fields{
2954 "intf-id": intfID,
2955 "onu-id": onuID,
2956 "gemPort": gemPort,
2957 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002958 return
2959 }
Shrey Baid26912972020-04-16 21:02:31 +05302960 logger.Infow("gem-added-to-onu-info-map",
2961 log.Fields{
Matteo Scandolo60913ed2020-06-23 19:31:14 -07002962 "gem-port-id": gemPort,
2963 "intf-id": intfID,
2964 "onu-id": onuID,
2965 "device-id": f.deviceHandler.device.Id,
2966 "onu-gem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002967}
2968
2969// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002970
2971//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 -07002972func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302973
Matteo Scandolo60913ed2020-06-23 19:31:14 -07002974 f.onuGemInfoLock.RLock()
2975 defer f.onuGemInfoLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302976
Shrey Baid26912972020-04-16 21:02:31 +05302977 logger.Infow("getting-onu-id-from-gem-port-and-pon-port",
2978 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002979 "device-id": f.deviceHandler.device.Id,
2980 "onu-geminfo": f.onuGemInfo[intfID],
2981 "intf-id": intfID,
2982 "gemport-id": gemPortID})
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002983
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302984 // get onuid from the onugem info cache
2985 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002986
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302987 for _, onu := range onugem {
2988 for _, gem := range onu.GemPorts {
2989 if gem == gemPortID {
2990 return onu.OnuID, nil
2991 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002992 }
2993 }
Matteo Scandolo60913ed2020-06-23 19:31:14 -07002994 logger.Errorw("onu-id-from-gem-port-not-found", log.Fields{
2995 "gem-port-id": gemPortID,
2996 "interface-id": intfID,
2997 "all-gems-on-port": onu,
2998 })
Thomas Lee S94109f12020-03-03 16:39:29 +05302999 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003000 "interface-id": intfID,
3001 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00003002 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003003}
3004
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003005//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05303006func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003007 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003008 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003009 var err error
3010
3011 if packetIn.IntfType == "pon" {
3012 // packet indication does not have serial number , so sending as nil
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003013 if onuID, err = f.getOnuIDfromGemPortMap(packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003014 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003015 return logicalPortNum, err
3016 }
3017 if packetIn.PortNo != 0 {
3018 logicalPortNum = packetIn.PortNo
3019 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003020 uniID := uint32(0) // FIXME - multi-uni support
3021 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003022 }
3023 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
Esin Karaman04166c82020-07-16 14:23:33 +00003024 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003025 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003026 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003027 }
Shrey Baid26912972020-04-16 21:02:31 +05303028 logger.Infow("retrieved-logicalport-from-packet-in",
3029 log.Fields{
3030 "logical-port-num": logicalPortNum,
3031 "intf-type": packetIn.IntfType,
3032 "packet": hex.EncodeToString(packetIn.Pkt),
3033 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003034 return logicalPortNum, nil
3035}
3036
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003037//GetPacketOutGemPortID returns gemPortId
Esin Karaman04166c82020-07-16 14:23:33 +00003038func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003039 var gemPortID uint32
Esin Karaman04166c82020-07-16 14:23:33 +00003040
3041 ctag, priority, err := getCTagFromPacket(ctx, packet)
3042 if err != nil {
3043 return 0, err
3044 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303045
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003046 f.onuGemInfoLock.RLock()
3047 defer f.onuGemInfoLock.RUnlock()
Esin Karaman04166c82020-07-16 14:23:33 +00003048 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003049 var ok bool
3050 gemPortID, ok = f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303051 if ok {
Shrey Baid26912972020-04-16 21:02:31 +05303052 logger.Debugw("found-gemport-for-pktin-key",
3053 log.Fields{
3054 "pktinkey": pktInkey,
3055 "gem": gemPortID})
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003056
3057 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003058 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303059 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
Esin Karaman04166c82020-07-16 14:23:33 +00003060 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303061 if err == nil {
3062 if gemPortID != 0 {
3063 f.packetInGemPort[pktInkey] = gemPortID
Shrey Baid26912972020-04-16 21:02:31 +05303064 logger.Infow("found-gem-port-from-kv-store-and-updating-cache-with-gemport",
3065 log.Fields{
3066 "pktinkey": pktInkey,
3067 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303068 return gemPortID, nil
3069 }
3070 }
Shrey Baid26912972020-04-16 21:02:31 +05303071 return uint32(0), olterrors.NewErrNotFound("gem-port",
3072 log.Fields{
3073 "pktinkey": pktInkey,
3074 "gem": gemPortID}, err)
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003075
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003076}
3077
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003078// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303079func installFlowOnAllGemports(ctx context.Context,
3080 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003081 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003082 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05303083 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303084 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303085 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003086 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003087 args map[string]uint32,
3088 classifier map[string]interface{}, action map[string]interface{},
3089 logicalFlow *ofp.OfpFlowStats,
3090 gemPorts []uint32,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003091 TpInst interface{},
Manikkaraj kb1d51442019-07-23 10:41:02 -04003092 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00003093 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003094 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003095 vlanID ...uint32) {
Shrey Baid26912972020-04-16 21:02:31 +05303096 logger.Debugw("installing-flow-on-all-gem-ports",
3097 log.Fields{
3098 "FlowType": FlowType,
3099 "gemPorts": gemPorts,
3100 "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05303101
Gamze Abaka724d0852020-03-18 12:10:24 +00003102 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
3103 // We need to trim prefix "0b", before further processing
3104 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
3105 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
3106
3107 // If a particular character in the string is set to '1', identify the index of this character from
3108 // the LSB position which marks the PCP bit consumed by the given gem port.
3109 // This PCP bit now becomes a classifier in the flow.
3110
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003111 switch TpInst := TpInst.(type) {
3112 case *tp.TechProfile:
3113 attributes := TpInst.DownstreamGemPortAttributeList
3114 if direction == Upstream {
3115 attributes = TpInst.UpstreamGemPortAttributeList
Gamze Abaka724d0852020-03-18 12:10:24 +00003116 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003117
3118 for _, gemPortAttribute := range attributes {
3119 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
3120 continue
Gamze Abaka724d0852020-03-18 12:10:24 +00003121 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003122 gemPortID := gemPortAttribute.GemportID
3123 if allPbitsMarked(gemPortAttribute.PbitMap) {
3124 classifier[VlanPcp] = uint32(VlanPCPMask)
3125 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3126 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3127 } else if FlowType == EapolFlow {
3128 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3129 }
3130 } else {
3131 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
3132 if pbitSet == BinaryBit1 {
3133 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3134 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3135 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3136 } else if FlowType == EapolFlow {
3137 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3138 }
3139 }
3140 }
3141 }
3142 }
3143 case *tp.EponProfile:
3144 if direction == Upstream {
3145 attributes := TpInst.UpstreamQueueAttributeList
3146 for _, queueAttribute := range attributes {
3147 gemPortID := queueAttribute.GemportID
3148 if allPbitsMarked(queueAttribute.PbitMap) {
3149 classifier[VlanPcp] = uint32(VlanPCPMask)
Gamze Abaka724d0852020-03-18 12:10:24 +00003150 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003151 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003152 } else if FlowType == EapolFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003153 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 +00003154 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003155 } else {
3156 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3157 if pbitSet == BinaryBit1 {
3158 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3159 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3160 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3161 } else if FlowType == EapolFlow {
3162 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3163 }
3164 }
3165 }
3166 }
3167 }
3168 } else {
3169 attributes := TpInst.DownstreamQueueAttributeList
3170 for _, queueAttribute := range attributes {
3171 gemPortID := queueAttribute.GemportID
3172 if allPbitsMarked(queueAttribute.PbitMap) {
3173 classifier[VlanPcp] = uint32(VlanPCPMask)
3174 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3175 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3176 } else if FlowType == EapolFlow {
3177 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3178 }
3179 } else {
3180 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3181 if pbitSet == BinaryBit1 {
3182 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3183 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3184 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3185 } else if FlowType == EapolFlow {
3186 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3187 }
3188 }
3189 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05303190 }
3191 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04003192 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003193 default:
3194 logger.Errorw("unknown-tech", log.Fields{"tpInst": TpInst})
Manikkaraj kb1d51442019-07-23 10:41:02 -04003195 }
3196}
3197
Gamze Abaka724d0852020-03-18 12:10:24 +00003198func allPbitsMarked(pbitMap string) bool {
3199 for pos, pBit := range pbitMap {
3200 if pos >= 2 && pBit != BinaryBit1 {
3201 return false
3202 }
3203 }
3204 return true
3205}
3206
David K. Bainbridge794735f2020-02-11 21:01:37 -08003207func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05303208 logger.Debug("adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003209 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003210 classifier[PacketTagType] = DoubleTag
3211 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003212 /* We manage flowId resource pool on per PON port basis.
3213 Since this situation is tricky, as a hack, we pass the NNI port
3214 index (network_intf_id) as PON port Index for the flowId resource
3215 pool. Also, there is no ONU Id available for trapping DHCP packets
3216 on NNI port, use onu_id as -1 (invalid)
3217 ****************** CAVEAT *******************
3218 This logic works if the NNI Port Id falls within the same valid
3219 range of PON Port Ids. If this doesn't work for some OLT Vendor
3220 we need to have a re-look at this.
3221 *********************************************
3222 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003223 onuID := -1
3224 uniID := -1
3225 gemPortID := -1
3226 allocID := -1
David K. Bainbridge794735f2020-02-11 21:01:37 -08003227 networkInterfaceID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303228 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303229 return olterrors.NewErrNotFound("nni-intreface-id",
3230 log.Fields{
3231 "classifier": classifier,
3232 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003233 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303234 }
3235
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003236 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303237 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05303238 logger.Info("flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003239 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003240 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003241 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003242 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303243 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id",
3244 log.Fields{
3245 "interface-id": networkInterfaceID,
3246 "onu-id": onuID,
3247 "uni-id": uniID,
3248 "gem-port-id": gemPortID,
3249 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003250 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003251 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003252 classifierProto, err := makeOpenOltClassifierField(classifier)
3253 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003254 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003255 }
Shrey Baid26912972020-04-16 21:02:31 +05303256 logger.Debugw("created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003257 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003258 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003259 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003260 }
Shrey Baid26912972020-04-16 21:02:31 +05303261 logger.Debugw("created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003262 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3263 OnuId: int32(onuID), // OnuId not required
3264 UniId: int32(uniID), // UniId not used
3265 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07003266 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003267 AllocId: int32(allocID), // AllocId not used
3268 NetworkIntfId: int32(networkInterfaceID),
3269 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003270 Classifier: classifierProto,
3271 Action: actionProto,
3272 Priority: int32(logicalFlow.Priority),
3273 Cookie: logicalFlow.Cookie,
3274 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003275 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003276 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003277 }
Shrey Baid26912972020-04-16 21:02:31 +05303278 logger.Info("dhcp-trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003279 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3280 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3281 int32(onuID),
3282 int32(uniID),
3283 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003284 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003285 }
3286 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003287}
salmansiddiqui7ac62132019-08-22 03:58:50 +00003288
Esin Karamanae41e2b2019-12-17 18:13:13 +00003289//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
3290func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
3291 var packetType string
3292 ovid, ivid := false, false
3293 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
3294 vid := vlanID & VlanvIDMask
3295 if vid != ReservedVlan {
3296 ovid = true
3297 }
3298 }
3299 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
3300 vid := uint32(metadata)
3301 if vid != ReservedVlan {
3302 ivid = true
3303 }
3304 }
3305 if ovid && ivid {
3306 packetType = DoubleTag
3307 } else if !ovid && !ivid {
3308 packetType = Untagged
3309 } else {
3310 packetType = SingleTag
3311 }
3312 return packetType
3313}
3314
3315//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08003316func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05303317 logger.Infow("adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003318 action := make(map[string]interface{})
3319 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
3320 action[TrapToHost] = true
3321 /* We manage flowId resource pool on per PON port basis.
3322 Since this situation is tricky, as a hack, we pass the NNI port
3323 index (network_intf_id) as PON port Index for the flowId resource
3324 pool. Also, there is no ONU Id available for trapping packets
3325 on NNI port, use onu_id as -1 (invalid)
3326 ****************** CAVEAT *******************
3327 This logic works if the NNI Port Id falls within the same valid
3328 range of PON Port Ids. If this doesn't work for some OLT Vendor
3329 we need to have a re-look at this.
3330 *********************************************
3331 */
3332 onuID := -1
3333 uniID := -1
3334 gemPortID := -1
3335 allocID := -1
3336 networkInterfaceID, err := getNniIntfID(classifier, action)
3337 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303338 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003339 "classifier": classifier,
3340 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003341 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003342 }
3343 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303344 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05303345 logger.Info("igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003346 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003347 }
npujarec5762e2020-01-01 14:08:48 +05303348 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003349 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303350 return olterrors.NewErrNotFound("igmp-flow-id",
3351 log.Fields{
3352 "interface-id": networkInterfaceID,
3353 "onu-id": onuID,
3354 "uni-id": uniID,
3355 "gem-port-id": gemPortID,
3356 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003357 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003358 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003359 classifierProto, err := makeOpenOltClassifierField(classifier)
3360 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003361 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003362 }
Shrey Baid26912972020-04-16 21:02:31 +05303363 logger.Debugw("created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003364 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003365 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003366 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003367 }
Shrey Baid26912972020-04-16 21:02:31 +05303368 logger.Debugw("created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003369 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3370 OnuId: int32(onuID), // OnuId not required
3371 UniId: int32(uniID), // UniId not used
3372 FlowId: flowID,
3373 FlowType: Downstream,
3374 AllocId: int32(allocID), // AllocId not used
3375 NetworkIntfId: int32(networkInterfaceID),
3376 GemportId: int32(gemPortID), // GemportId not used
3377 Classifier: classifierProto,
3378 Action: actionProto,
3379 Priority: int32(logicalFlow.Priority),
3380 Cookie: logicalFlow.Cookie,
3381 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003382 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003383 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003384 }
Shrey Baid26912972020-04-16 21:02:31 +05303385 logger.Info("igmp-trap-on-nni-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003386 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3387 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3388 int32(onuID),
3389 int32(uniID),
3390 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003391 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003392 }
3393 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003394}
3395
salmansiddiqui7ac62132019-08-22 03:58:50 +00003396func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
3397 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05303398 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003399 }
3400 if Dir == tp_pb.Direction_UPSTREAM {
3401 return "upstream", nil
3402 } else if Dir == tp_pb.Direction_DOWNSTREAM {
3403 return "downstream", nil
3404 }
3405 return "", nil
3406}
3407
npujarec5762e2020-01-01 14:08:48 +05303408func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003409 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003410 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00003411 var gemPort uint32
3412 intfID := args[IntfID]
3413 onuID := args[OnuID]
3414 uniID := args[UniID]
3415 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003416 allocID := args[AllocID]
salmansiddiqui7ac62132019-08-22 03:58:50 +00003417 if ipProto, ok := classifierInfo[IPProto]; ok {
3418 if ipProto.(uint32) == IPProtoDhcp {
Matteo Scandolo92186242020-06-12 10:54:18 -07003419 logger.Infow("adding-dhcp-flow", log.Fields{
3420 "tp-id": tpID,
3421 "alloc-id": allocID,
3422 "intf-id": intfID,
3423 "onu-id": onuID,
3424 "uni-id": uniID,
3425 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003426 if pcp, ok := classifierInfo[VlanPcp]; ok {
3427 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3428 tp_pb.Direction_UPSTREAM,
3429 pcp.(uint32))
3430 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00003431
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003432 f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003433 } else {
3434 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003435 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003436 }
3437
Girish Gowdra32625212020-04-29 11:26:35 -07003438 } else if ipProto.(uint32) == IgmpProto {
Shrey Baid26912972020-04-16 21:02:31 +05303439 logger.Infow("adding-us-igmp-flow",
3440 log.Fields{
3441 "intf-id": intfID,
3442 "onu-id": onuID,
3443 "uni-id": uniID,
3444 "classifier-info:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003445 if pcp, ok := classifierInfo[VlanPcp]; ok {
3446 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3447 tp_pb.Direction_UPSTREAM,
3448 pcp.(uint32))
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003449 f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003450 } else {
3451 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003452 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003453 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003454 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303455 logger.Errorw("invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003456 return
3457 }
3458 } else if ethType, ok := classifierInfo[EthType]; ok {
3459 if ethType.(uint32) == EapEthType {
Matteo Scandolo92186242020-06-12 10:54:18 -07003460 logger.Infow("adding-eapol-flow", log.Fields{
3461 "intf-id": intfID,
3462 "onu-id": onuID,
3463 "uni-id": uniID,
3464 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003465 var vlanID uint32
3466 if val, ok := classifierInfo[VlanVid]; ok {
3467 vlanID = (val.(uint32)) & VlanvIDMask
3468 } else {
3469 vlanID = DefaultMgmtVlan
3470 }
3471 if pcp, ok := classifierInfo[VlanPcp]; ok {
3472 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3473 tp_pb.Direction_UPSTREAM,
3474 pcp.(uint32))
3475
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003476 f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003477 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003478 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003479 }
3480 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003481 } else if _, ok := actionInfo[PushVlan]; ok {
Matteo Scandolo92186242020-06-12 10:54:18 -07003482 logger.Infow("adding-upstream-data-rule", log.Fields{
3483 "intf-id": intfID,
3484 "onu-id": onuID,
3485 "uni-id": uniID,
3486 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003487 if pcp, ok := classifierInfo[VlanPcp]; ok {
3488 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3489 tp_pb.Direction_UPSTREAM,
3490 pcp.(uint32))
3491 //Adding HSIA upstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003492 f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003493 } else {
3494 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003495 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003496 }
3497 } else if _, ok := actionInfo[PopVlan]; ok {
Matteo Scandolo92186242020-06-12 10:54:18 -07003498 logger.Infow("adding-downstream-data-rule", log.Fields{
3499 "intf-id": intfID,
3500 "onu-id": onuID,
3501 "uni-id": uniID,
3502 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003503 if pcp, ok := classifierInfo[VlanPcp]; ok {
3504 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05003505 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003506 pcp.(uint32))
3507 //Adding HSIA downstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003508 f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003509 } else {
3510 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003511 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003512 }
3513 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303514 logger.Errorw("invalid-flow-type-to-handle",
3515 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003516 "intf-id": intfID,
3517 "onu-id": onuID,
3518 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05303519 "classifier": classifierInfo,
3520 "action": actionInfo,
3521 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003522 return
3523 }
3524 // Send Techprofile download event to child device in go routine as it takes time
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003525 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003526}
3527
Gamze Abakafee36392019-10-03 11:17:24 +00003528func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
3529 flowIDList := f.flowsUsedByGemPort[gemPK]
3530 if len(flowIDList) > 1 {
3531 return true
3532 }
3533 return false
3534}
3535
npujarec5762e2020-01-01 14:08:48 +05303536func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3537 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003538 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3539 for _, currentGemPort := range currentGemPorts {
3540 for _, tpGemPort := range tpGemPorts {
3541 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3542 return true, currentGemPort
3543 }
3544 }
3545 }
Girish Gowdra54934262019-11-13 14:19:55 +05303546 if tpInst.InstanceCtrl.Onu == "single-instance" {
3547 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
npujarec5762e2020-01-01 14:08:48 +05303548 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID)
3549 f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID)
Girish Gowdra54934262019-11-13 14:19:55 +05303550
3551 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3552 // still be used on other uni ports.
3553 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3554 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003555 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Shrey Baid26912972020-04-16 21:02:31 +05303556 logger.Debugw("got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303557 for i := 0; i < len(tpInstances); i++ {
3558 tpI := tpInstances[i]
3559 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303560 for _, tpGemPort := range tpGemPorts {
3561 if tpGemPort.GemportID != gemPortID {
Shrey Baid26912972020-04-16 21:02:31 +05303562 logger.Debugw("single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303563 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303564 }
3565 }
3566 }
3567 }
Shrey Baid26912972020-04-16 21:02:31 +05303568 logger.Debug("tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003569 return false, 0
3570}
3571
salmansiddiqui7ac62132019-08-22 03:58:50 +00003572func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003573 for _, field := range flows.GetOfbFields(flow) {
3574 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003575 classifierInfo[EthType] = field.GetEthType()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003576 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003577 } else if field.Type == flows.ETH_DST {
3578 classifierInfo[EthDst] = field.GetEthDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003579 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003580 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003581 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003582 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003583 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003584 classifierInfo[InPort] = field.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003585 logger.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003586 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303587 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00003588 logger.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003589 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003590 classifierInfo[VlanPcp] = field.GetVlanPcp()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003591 logger.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003592 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003593 classifierInfo[UDPDst] = field.GetUdpDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003594 logger.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003595 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003596 classifierInfo[UDPSrc] = field.GetUdpSrc()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003597 logger.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003598 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003599 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003600 logger.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003601 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003602 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003603 logger.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003604 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003605 classifierInfo[Metadata] = field.GetTableMetadata()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003606 logger.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003607 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003608 classifierInfo[TunnelID] = field.GetTunnelId()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003609 logger.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003610 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303611 logger.Errorw("un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003612 return
3613 }
3614 }
3615}
3616
3617func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003618 for _, action := range flows.GetActions(flow) {
3619 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003620 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003621 actionInfo[Output] = out.GetPort()
Shrey Baid26912972020-04-16 21:02:31 +05303622 logger.Debugw("action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003623 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003624 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003625 }
Scott Baker355d1742019-10-24 10:57:52 -07003626 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003627 actionInfo[PopVlan] = true
Girish Kumar2ad402b2020-03-20 19:45:12 +00003628 logger.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003629 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003630 if out := action.GetPush(); out != nil {
3631 if tpid := out.GetEthertype(); tpid != 0x8100 {
Shrey Baid26912972020-04-16 21:02:31 +05303632 logger.Errorw("invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003633 } else {
3634 actionInfo[PushVlan] = true
3635 actionInfo[TPID] = tpid
Girish Kumar2ad402b2020-03-20 19:45:12 +00003636 logger.Debugw("action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303637 log.Fields{
3638 "push-tpid": actionInfo[TPID].(uint32),
3639 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003640 }
3641 }
Scott Baker355d1742019-10-24 10:57:52 -07003642 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003643 if out := action.GetSetField(); out != nil {
3644 if field := out.GetField(); field != nil {
3645 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003646 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003647 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00003648 /*logger.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
Esin Karamanccb714b2019-11-29 15:02:06 +00003649 formulateSetFieldActionInfoFromFlow(field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003650 }
3651 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003652 } else if action.Type == flows.GROUP {
3653 formulateGroupActionInfoFromFlow(action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003654 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003655 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003656 }
3657 }
3658 return nil
3659}
3660
Esin Karamanccb714b2019-11-29 15:02:06 +00003661func formulateSetFieldActionInfoFromFlow(field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
3662 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003663 fieldtype := ofbField.GetType()
3664 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003665 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3666 actionInfo[VlanVid] = vlan & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00003667 logger.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003668 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303669 logger.Error("no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003670 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003671 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3672 pcp := ofbField.GetVlanPcp()
3673 actionInfo[VlanPcp] = pcp
3674 log.Debugw("action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003675 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003676 logger.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003677 }
3678 }
3679}
3680
3681func formulateGroupActionInfoFromFlow(action *ofp.OfpAction, actionInfo map[string]interface{}) {
3682 if action.GetGroup() == nil {
Shrey Baid26912972020-04-16 21:02:31 +05303683 logger.Warn("no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003684 } else {
3685 actionInfo[GroupID] = action.GetGroup().GroupId
Girish Kumar2ad402b2020-03-20 19:45:12 +00003686 logger.Debugw("action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003687 }
3688}
3689
salmansiddiqui7ac62132019-08-22 03:58:50 +00003690func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003691 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Shrey Baid26912972020-04-16 21:02:31 +05303692 logger.Debug("controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003693 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3694 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003695 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003696 classifierInfo[InPort] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303697 logger.Debugw("upstream-pon-to-controller-flow--inport-in-tunnelid",
3698 log.Fields{
3699 "newinport": classifierInfo[InPort].(uint32),
3700 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003701 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303702 return olterrors.NewErrNotFound("child-in-port",
3703 log.Fields{
3704 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3705 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003706 }
3707 }
3708 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303709 logger.Debug("non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003710 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003711 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003712 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003713 actionInfo[Output] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303714 logger.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid",
3715 log.Fields{
3716 "newoutport": actionInfo[Output].(uint32),
3717 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003718 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303719 return olterrors.NewErrNotFound("out-port",
3720 log.Fields{
3721 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3722 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003723 }
3724 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3725 } else 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-nni-port-flow, inport-in-tunnelid",
3729 log.Fields{
3730 "newinport": actionInfo[Output].(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("nni-port",
3734 log.Fields{
3735 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3736 "in-port": classifierInfo[InPort].(uint32),
3737 "out-port": actionInfo[Output].(uint32),
3738 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003739 }
3740 }
3741 }
3742 return nil
3743}
Gamze Abakafee36392019-10-03 11:17:24 +00003744
Chaitrashree G S90a17952019-11-14 21:51:21 -05003745func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003746 /* Metadata 8 bytes:
3747 Most Significant 2 Bytes = Inner VLAN
3748 Next 2 Bytes = Tech Profile ID(TPID)
3749 Least Significant 4 Bytes = Port ID
3750 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3751 subscriber related flows.
3752 */
3753 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
3754 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003755 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003756 }
3757 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003758 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003759}
3760
3761func appendUnique(slice []uint32, item uint32) []uint32 {
3762 for _, sliceElement := range slice {
3763 if sliceElement == item {
3764 return slice
3765 }
3766 }
3767 return append(slice, item)
3768}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303769
3770// getNniIntfID gets nni intf id from the flow classifier/action
3771func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
3772
3773 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3774 if portType == voltha.Port_PON_OLT {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003775 intfID, err := IntfIDFromNniPortNum(action[Output].(uint32))
3776 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003777 logger.Debugw("invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003778 log.Fields{
3779 "port-number": action[Output].(uint32),
3780 "error": err})
3781 return uint32(0), err
3782 }
Shrey Baid26912972020-04-16 21:02:31 +05303783 logger.Infow("output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303784 return intfID, nil
3785 } else if portType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003786 intfID, err := IntfIDFromNniPortNum(classifier[InPort].(uint32))
3787 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003788 logger.Debugw("invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003789 log.Fields{
3790 "port-number": action[Output].(uint32),
3791 "error": err})
3792 return uint32(0), err
3793 }
Shrey Baid26912972020-04-16 21:02:31 +05303794 logger.Infow("input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303795 return intfID, nil
3796 }
3797 return uint32(0), nil
3798}
3799
3800// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman04166c82020-07-16 14:23:33 +00003801func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3802 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3803 if err != nil {
3804 logger.Errorw("unable-to-update-gem-port-for-packet-in",
3805 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3806 return
3807 }
3808 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003809
3810 f.onuGemInfoLock.Lock()
3811 defer f.onuGemInfoLock.Unlock()
3812
Matt Jeanneret1719a072019-12-20 14:50:14 -05003813 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303814 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003815 if lookupGemPort == gemPort {
Shrey Baid26912972020-04-16 21:02:31 +05303816 logger.Infow("pktin-key/value-found-in-cache--no-need-to-update-kv--assume-both-in-sync",
3817 log.Fields{
3818 "pktinkey": pktInkey,
3819 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003820 return
3821 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303822 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003823 f.packetInGemPort[pktInkey] = gemPort
3824
npujarec5762e2020-01-01 14:08:48 +05303825 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Shrey Baid26912972020-04-16 21:02:31 +05303826 logger.Infow("pktin-key-not-found-in-local-cache-value-is-different--updating-cache-and-kv-store",
3827 log.Fields{
3828 "pktinkey": pktInkey,
3829 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303830 return
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003831
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303832}
3833
Esin Karaman04166c82020-07-16 14:23:33 +00003834//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3835func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3836 if packet == nil || len(packet) < 18 {
3837 log.Error("unable-get-c-tag-from-the-packet--invalid-packet-length ")
3838 return 0, 0, errors.New("invalid packet length")
3839 }
3840 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3841 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3842
3843 var index int8
3844 if outerEthType == 0x8100 {
3845 if innerEthType == 0x8100 {
3846 // q-in-q 802.1ad or 802.1q double tagged packet.
3847 // get the inner vlanId
3848 index = 18
3849 } else {
3850 index = 14
3851 }
3852 priority := (packet[index] >> 5) & 0x7
3853 //13 bits composes vlanId value
3854 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3855 return vlan, priority, nil
3856 }
3857 logger.Debugf("No vlanId found in the packet. Returning zero as c-tag")
3858 return 0, 0, nil
3859}
3860
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303861// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303862func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003863
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003864 f.onuGemInfoLock.Lock()
3865 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003866
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303867 onugem := f.onuGemInfo[intfID]
3868 for idx, onu := range onugem {
3869 if onu.OnuID == onuID {
3870 for _, uni := range onu.UniPorts {
3871 if uni == portNum {
Shrey Baid26912972020-04-16 21:02:31 +05303872 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 +05303873 return
3874 }
3875 }
3876 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3877 f.onuGemInfo[intfID] = onugem
3878 }
3879 }
npujarec5762e2020-01-01 14:08:48 +05303880 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003881
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303882}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303883
npujarec5762e2020-01-01 14:08:48 +05303884func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3885 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303886 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303887 logger.Error("failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303888 return
3889 }
3890 for gem, FlowIDs := range flowIDsList {
3891 gemPK := gemPortKey{intf, uint32(gem)}
3892 f.flowsUsedByGemPort[gemPK] = FlowIDs
3893 }
3894 return
3895}
Esin Karamanccb714b2019-11-29 15:02:06 +00003896
3897//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
3898//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05303899func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
3900 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00003901 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303902 logger.Error("failed-to-get-pon-interface-to-multicast-queue-map")
Esin Karamanccb714b2019-11-29 15:02:06 +00003903 return
3904 }
3905 for intf, queueInfo := range storedMulticastQueueMap {
3906 q := queueInfoBrief{
3907 gemPortID: queueInfo[0],
3908 servicePriority: queueInfo[1],
3909 }
3910 f.interfaceToMcastQueueMap[intf] = &q
3911 }
3912}
3913
3914//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
3915//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
3916//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05303917func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
3918 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00003919 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003920 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00003921 }
3922 if exists {
3923 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
3924 }
3925 return nil, exists, nil
3926}
3927
3928func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
3929 groupDesc := ofp.OfpGroupDesc{
3930 Type: ofp.OfpGroupType_OFPGT_ALL,
3931 GroupId: groupID,
3932 }
3933 groupEntry := ofp.OfpGroupEntry{
3934 Desc: &groupDesc,
3935 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003936 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003937 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00003938 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003939 bucket := ofp.OfpBucket{
3940 Actions: acts,
3941 }
3942 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00003943 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003944 return &groupEntry
3945}