blob: ef2248cc15f0c50a9d18eb8d0de594e1206909bf [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
npujarec5762e2020-01-01 14:08:48 +05303024 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
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
npujarec5762e2020-01-01 14:08:48 +05303038func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003039 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003040 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303041
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003042 f.onuGemInfoLock.RLock()
3043 defer f.onuGemInfoLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303044 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003045 var ok bool
3046 gemPortID, ok = f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303047 if ok {
Shrey Baid26912972020-04-16 21:02:31 +05303048 logger.Debugw("found-gemport-for-pktin-key",
3049 log.Fields{
3050 "pktinkey": pktInkey,
3051 "gem": gemPortID})
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003052
3053 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003054 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303055 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
npujarec5762e2020-01-01 14:08:48 +05303056 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303057 if err == nil {
3058 if gemPortID != 0 {
3059 f.packetInGemPort[pktInkey] = gemPortID
Shrey Baid26912972020-04-16 21:02:31 +05303060 logger.Infow("found-gem-port-from-kv-store-and-updating-cache-with-gemport",
3061 log.Fields{
3062 "pktinkey": pktInkey,
3063 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303064 return gemPortID, nil
3065 }
3066 }
Shrey Baid26912972020-04-16 21:02:31 +05303067 return uint32(0), olterrors.NewErrNotFound("gem-port",
3068 log.Fields{
3069 "pktinkey": pktInkey,
3070 "gem": gemPortID}, err)
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003071
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003072}
3073
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003074// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303075func installFlowOnAllGemports(ctx context.Context,
3076 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003077 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003078 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05303079 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303080 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303081 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003082 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003083 args map[string]uint32,
3084 classifier map[string]interface{}, action map[string]interface{},
3085 logicalFlow *ofp.OfpFlowStats,
3086 gemPorts []uint32,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003087 TpInst interface{},
Manikkaraj kb1d51442019-07-23 10:41:02 -04003088 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00003089 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003090 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003091 vlanID ...uint32) {
Shrey Baid26912972020-04-16 21:02:31 +05303092 logger.Debugw("installing-flow-on-all-gem-ports",
3093 log.Fields{
3094 "FlowType": FlowType,
3095 "gemPorts": gemPorts,
3096 "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05303097
Gamze Abaka724d0852020-03-18 12:10:24 +00003098 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
3099 // We need to trim prefix "0b", before further processing
3100 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
3101 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
3102
3103 // If a particular character in the string is set to '1', identify the index of this character from
3104 // the LSB position which marks the PCP bit consumed by the given gem port.
3105 // This PCP bit now becomes a classifier in the flow.
3106
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003107 switch TpInst := TpInst.(type) {
3108 case *tp.TechProfile:
3109 attributes := TpInst.DownstreamGemPortAttributeList
3110 if direction == Upstream {
3111 attributes = TpInst.UpstreamGemPortAttributeList
Gamze Abaka724d0852020-03-18 12:10:24 +00003112 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003113
3114 for _, gemPortAttribute := range attributes {
3115 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
3116 continue
Gamze Abaka724d0852020-03-18 12:10:24 +00003117 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003118 gemPortID := gemPortAttribute.GemportID
3119 if allPbitsMarked(gemPortAttribute.PbitMap) {
3120 classifier[VlanPcp] = uint32(VlanPCPMask)
3121 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3122 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3123 } else if FlowType == EapolFlow {
3124 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3125 }
3126 } else {
3127 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
3128 if pbitSet == BinaryBit1 {
3129 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3130 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3131 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3132 } else if FlowType == EapolFlow {
3133 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3134 }
3135 }
3136 }
3137 }
3138 }
3139 case *tp.EponProfile:
3140 if direction == Upstream {
3141 attributes := TpInst.UpstreamQueueAttributeList
3142 for _, queueAttribute := range attributes {
3143 gemPortID := queueAttribute.GemportID
3144 if allPbitsMarked(queueAttribute.PbitMap) {
3145 classifier[VlanPcp] = uint32(VlanPCPMask)
Gamze Abaka724d0852020-03-18 12:10:24 +00003146 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003147 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003148 } else if FlowType == EapolFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003149 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 +00003150 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003151 } else {
3152 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3153 if pbitSet == BinaryBit1 {
3154 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3155 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3156 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3157 } else if FlowType == EapolFlow {
3158 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3159 }
3160 }
3161 }
3162 }
3163 }
3164 } else {
3165 attributes := TpInst.DownstreamQueueAttributeList
3166 for _, queueAttribute := range attributes {
3167 gemPortID := queueAttribute.GemportID
3168 if allPbitsMarked(queueAttribute.PbitMap) {
3169 classifier[VlanPcp] = uint32(VlanPCPMask)
3170 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3171 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3172 } else if FlowType == EapolFlow {
3173 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3174 }
3175 } else {
3176 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3177 if pbitSet == BinaryBit1 {
3178 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3179 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3180 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3181 } else if FlowType == EapolFlow {
3182 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3183 }
3184 }
3185 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05303186 }
3187 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04003188 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003189 default:
3190 logger.Errorw("unknown-tech", log.Fields{"tpInst": TpInst})
Manikkaraj kb1d51442019-07-23 10:41:02 -04003191 }
3192}
3193
Gamze Abaka724d0852020-03-18 12:10:24 +00003194func allPbitsMarked(pbitMap string) bool {
3195 for pos, pBit := range pbitMap {
3196 if pos >= 2 && pBit != BinaryBit1 {
3197 return false
3198 }
3199 }
3200 return true
3201}
3202
David K. Bainbridge794735f2020-02-11 21:01:37 -08003203func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05303204 logger.Debug("adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003205 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003206 classifier[PacketTagType] = DoubleTag
3207 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003208 /* We manage flowId resource pool on per PON port basis.
3209 Since this situation is tricky, as a hack, we pass the NNI port
3210 index (network_intf_id) as PON port Index for the flowId resource
3211 pool. Also, there is no ONU Id available for trapping DHCP packets
3212 on NNI port, use onu_id as -1 (invalid)
3213 ****************** CAVEAT *******************
3214 This logic works if the NNI Port Id falls within the same valid
3215 range of PON Port Ids. If this doesn't work for some OLT Vendor
3216 we need to have a re-look at this.
3217 *********************************************
3218 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003219 onuID := -1
3220 uniID := -1
3221 gemPortID := -1
3222 allocID := -1
David K. Bainbridge794735f2020-02-11 21:01:37 -08003223 networkInterfaceID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303224 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303225 return olterrors.NewErrNotFound("nni-intreface-id",
3226 log.Fields{
3227 "classifier": classifier,
3228 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003229 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303230 }
3231
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003232 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303233 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05303234 logger.Info("flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003235 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003236 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003237 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003238 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303239 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id",
3240 log.Fields{
3241 "interface-id": networkInterfaceID,
3242 "onu-id": onuID,
3243 "uni-id": uniID,
3244 "gem-port-id": gemPortID,
3245 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003246 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003247 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003248 classifierProto, err := makeOpenOltClassifierField(classifier)
3249 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003250 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003251 }
Shrey Baid26912972020-04-16 21:02:31 +05303252 logger.Debugw("created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003253 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003254 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003255 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003256 }
Shrey Baid26912972020-04-16 21:02:31 +05303257 logger.Debugw("created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003258 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3259 OnuId: int32(onuID), // OnuId not required
3260 UniId: int32(uniID), // UniId not used
3261 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07003262 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003263 AllocId: int32(allocID), // AllocId not used
3264 NetworkIntfId: int32(networkInterfaceID),
3265 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003266 Classifier: classifierProto,
3267 Action: actionProto,
3268 Priority: int32(logicalFlow.Priority),
3269 Cookie: logicalFlow.Cookie,
3270 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003271 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003272 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003273 }
Shrey Baid26912972020-04-16 21:02:31 +05303274 logger.Info("dhcp-trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003275 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3276 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3277 int32(onuID),
3278 int32(uniID),
3279 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003280 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003281 }
3282 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003283}
salmansiddiqui7ac62132019-08-22 03:58:50 +00003284
Esin Karamanae41e2b2019-12-17 18:13:13 +00003285//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
3286func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
3287 var packetType string
3288 ovid, ivid := false, false
3289 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
3290 vid := vlanID & VlanvIDMask
3291 if vid != ReservedVlan {
3292 ovid = true
3293 }
3294 }
3295 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
3296 vid := uint32(metadata)
3297 if vid != ReservedVlan {
3298 ivid = true
3299 }
3300 }
3301 if ovid && ivid {
3302 packetType = DoubleTag
3303 } else if !ovid && !ivid {
3304 packetType = Untagged
3305 } else {
3306 packetType = SingleTag
3307 }
3308 return packetType
3309}
3310
3311//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08003312func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05303313 logger.Infow("adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003314 action := make(map[string]interface{})
3315 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
3316 action[TrapToHost] = true
3317 /* We manage flowId resource pool on per PON port basis.
3318 Since this situation is tricky, as a hack, we pass the NNI port
3319 index (network_intf_id) as PON port Index for the flowId resource
3320 pool. Also, there is no ONU Id available for trapping packets
3321 on NNI port, use onu_id as -1 (invalid)
3322 ****************** CAVEAT *******************
3323 This logic works if the NNI Port Id falls within the same valid
3324 range of PON Port Ids. If this doesn't work for some OLT Vendor
3325 we need to have a re-look at this.
3326 *********************************************
3327 */
3328 onuID := -1
3329 uniID := -1
3330 gemPortID := -1
3331 allocID := -1
3332 networkInterfaceID, err := getNniIntfID(classifier, action)
3333 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303334 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003335 "classifier": classifier,
3336 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003337 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003338 }
3339 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303340 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05303341 logger.Info("igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003342 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003343 }
npujarec5762e2020-01-01 14:08:48 +05303344 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003345 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303346 return olterrors.NewErrNotFound("igmp-flow-id",
3347 log.Fields{
3348 "interface-id": networkInterfaceID,
3349 "onu-id": onuID,
3350 "uni-id": uniID,
3351 "gem-port-id": gemPortID,
3352 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003353 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003354 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003355 classifierProto, err := makeOpenOltClassifierField(classifier)
3356 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003357 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003358 }
Shrey Baid26912972020-04-16 21:02:31 +05303359 logger.Debugw("created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003360 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003361 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003362 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003363 }
Shrey Baid26912972020-04-16 21:02:31 +05303364 logger.Debugw("created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003365 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3366 OnuId: int32(onuID), // OnuId not required
3367 UniId: int32(uniID), // UniId not used
3368 FlowId: flowID,
3369 FlowType: Downstream,
3370 AllocId: int32(allocID), // AllocId not used
3371 NetworkIntfId: int32(networkInterfaceID),
3372 GemportId: int32(gemPortID), // GemportId not used
3373 Classifier: classifierProto,
3374 Action: actionProto,
3375 Priority: int32(logicalFlow.Priority),
3376 Cookie: logicalFlow.Cookie,
3377 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003378 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003379 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003380 }
Shrey Baid26912972020-04-16 21:02:31 +05303381 logger.Info("igmp-trap-on-nni-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003382 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3383 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3384 int32(onuID),
3385 int32(uniID),
3386 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003387 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003388 }
3389 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003390}
3391
salmansiddiqui7ac62132019-08-22 03:58:50 +00003392func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
3393 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05303394 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003395 }
3396 if Dir == tp_pb.Direction_UPSTREAM {
3397 return "upstream", nil
3398 } else if Dir == tp_pb.Direction_DOWNSTREAM {
3399 return "downstream", nil
3400 }
3401 return "", nil
3402}
3403
npujarec5762e2020-01-01 14:08:48 +05303404func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003405 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003406 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00003407 var gemPort uint32
3408 intfID := args[IntfID]
3409 onuID := args[OnuID]
3410 uniID := args[UniID]
3411 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003412 allocID := args[AllocID]
salmansiddiqui7ac62132019-08-22 03:58:50 +00003413 if ipProto, ok := classifierInfo[IPProto]; ok {
3414 if ipProto.(uint32) == IPProtoDhcp {
Matteo Scandolo92186242020-06-12 10:54:18 -07003415 logger.Infow("adding-dhcp-flow", log.Fields{
3416 "tp-id": tpID,
3417 "alloc-id": allocID,
3418 "intf-id": intfID,
3419 "onu-id": onuID,
3420 "uni-id": uniID,
3421 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003422 if pcp, ok := classifierInfo[VlanPcp]; ok {
3423 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3424 tp_pb.Direction_UPSTREAM,
3425 pcp.(uint32))
3426 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00003427
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003428 f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003429 } else {
3430 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003431 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003432 }
3433
Girish Gowdra32625212020-04-29 11:26:35 -07003434 } else if ipProto.(uint32) == IgmpProto {
Shrey Baid26912972020-04-16 21:02:31 +05303435 logger.Infow("adding-us-igmp-flow",
3436 log.Fields{
3437 "intf-id": intfID,
3438 "onu-id": onuID,
3439 "uni-id": uniID,
3440 "classifier-info:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003441 if pcp, ok := classifierInfo[VlanPcp]; ok {
3442 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3443 tp_pb.Direction_UPSTREAM,
3444 pcp.(uint32))
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003445 f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003446 } else {
3447 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003448 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003449 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003450 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303451 logger.Errorw("invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003452 return
3453 }
3454 } else if ethType, ok := classifierInfo[EthType]; ok {
3455 if ethType.(uint32) == EapEthType {
Matteo Scandolo92186242020-06-12 10:54:18 -07003456 logger.Infow("adding-eapol-flow", log.Fields{
3457 "intf-id": intfID,
3458 "onu-id": onuID,
3459 "uni-id": uniID,
3460 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003461 var vlanID uint32
3462 if val, ok := classifierInfo[VlanVid]; ok {
3463 vlanID = (val.(uint32)) & VlanvIDMask
3464 } else {
3465 vlanID = DefaultMgmtVlan
3466 }
3467 if pcp, ok := classifierInfo[VlanPcp]; ok {
3468 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3469 tp_pb.Direction_UPSTREAM,
3470 pcp.(uint32))
3471
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003472 f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003473 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003474 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003475 }
3476 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003477 } else if _, ok := actionInfo[PushVlan]; ok {
Matteo Scandolo92186242020-06-12 10:54:18 -07003478 logger.Infow("adding-upstream-data-rule", log.Fields{
3479 "intf-id": intfID,
3480 "onu-id": onuID,
3481 "uni-id": uniID,
3482 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003483 if pcp, ok := classifierInfo[VlanPcp]; ok {
3484 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3485 tp_pb.Direction_UPSTREAM,
3486 pcp.(uint32))
3487 //Adding HSIA upstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003488 f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003489 } else {
3490 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003491 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003492 }
3493 } else if _, ok := actionInfo[PopVlan]; ok {
Matteo Scandolo92186242020-06-12 10:54:18 -07003494 logger.Infow("adding-downstream-data-rule", log.Fields{
3495 "intf-id": intfID,
3496 "onu-id": onuID,
3497 "uni-id": uniID,
3498 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003499 if pcp, ok := classifierInfo[VlanPcp]; ok {
3500 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05003501 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003502 pcp.(uint32))
3503 //Adding HSIA downstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003504 f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003505 } else {
3506 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003507 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003508 }
3509 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303510 logger.Errorw("invalid-flow-type-to-handle",
3511 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003512 "intf-id": intfID,
3513 "onu-id": onuID,
3514 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05303515 "classifier": classifierInfo,
3516 "action": actionInfo,
3517 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003518 return
3519 }
3520 // Send Techprofile download event to child device in go routine as it takes time
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003521 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003522}
3523
Gamze Abakafee36392019-10-03 11:17:24 +00003524func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
3525 flowIDList := f.flowsUsedByGemPort[gemPK]
3526 if len(flowIDList) > 1 {
3527 return true
3528 }
3529 return false
3530}
3531
npujarec5762e2020-01-01 14:08:48 +05303532func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3533 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003534 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3535 for _, currentGemPort := range currentGemPorts {
3536 for _, tpGemPort := range tpGemPorts {
3537 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3538 return true, currentGemPort
3539 }
3540 }
3541 }
Girish Gowdra54934262019-11-13 14:19:55 +05303542 if tpInst.InstanceCtrl.Onu == "single-instance" {
3543 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
npujarec5762e2020-01-01 14:08:48 +05303544 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID)
3545 f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID)
Girish Gowdra54934262019-11-13 14:19:55 +05303546
3547 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3548 // still be used on other uni ports.
3549 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3550 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003551 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Shrey Baid26912972020-04-16 21:02:31 +05303552 logger.Debugw("got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303553 for i := 0; i < len(tpInstances); i++ {
3554 tpI := tpInstances[i]
3555 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303556 for _, tpGemPort := range tpGemPorts {
3557 if tpGemPort.GemportID != gemPortID {
Shrey Baid26912972020-04-16 21:02:31 +05303558 logger.Debugw("single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303559 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303560 }
3561 }
3562 }
3563 }
Shrey Baid26912972020-04-16 21:02:31 +05303564 logger.Debug("tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003565 return false, 0
3566}
3567
salmansiddiqui7ac62132019-08-22 03:58:50 +00003568func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003569 for _, field := range flows.GetOfbFields(flow) {
3570 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003571 classifierInfo[EthType] = field.GetEthType()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003572 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003573 } else if field.Type == flows.ETH_DST {
3574 classifierInfo[EthDst] = field.GetEthDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003575 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003576 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003577 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003578 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003579 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003580 classifierInfo[InPort] = field.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003581 logger.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003582 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303583 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00003584 logger.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003585 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003586 classifierInfo[VlanPcp] = field.GetVlanPcp()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003587 logger.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003588 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003589 classifierInfo[UDPDst] = field.GetUdpDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003590 logger.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003591 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003592 classifierInfo[UDPSrc] = field.GetUdpSrc()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003593 logger.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003594 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003595 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003596 logger.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003597 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003598 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003599 logger.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003600 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003601 classifierInfo[Metadata] = field.GetTableMetadata()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003602 logger.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003603 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003604 classifierInfo[TunnelID] = field.GetTunnelId()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003605 logger.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003606 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303607 logger.Errorw("un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003608 return
3609 }
3610 }
3611}
3612
3613func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003614 for _, action := range flows.GetActions(flow) {
3615 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003616 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003617 actionInfo[Output] = out.GetPort()
Shrey Baid26912972020-04-16 21:02:31 +05303618 logger.Debugw("action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003619 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003620 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003621 }
Scott Baker355d1742019-10-24 10:57:52 -07003622 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003623 actionInfo[PopVlan] = true
Girish Kumar2ad402b2020-03-20 19:45:12 +00003624 logger.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003625 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003626 if out := action.GetPush(); out != nil {
3627 if tpid := out.GetEthertype(); tpid != 0x8100 {
Shrey Baid26912972020-04-16 21:02:31 +05303628 logger.Errorw("invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003629 } else {
3630 actionInfo[PushVlan] = true
3631 actionInfo[TPID] = tpid
Girish Kumar2ad402b2020-03-20 19:45:12 +00003632 logger.Debugw("action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303633 log.Fields{
3634 "push-tpid": actionInfo[TPID].(uint32),
3635 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003636 }
3637 }
Scott Baker355d1742019-10-24 10:57:52 -07003638 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003639 if out := action.GetSetField(); out != nil {
3640 if field := out.GetField(); field != nil {
3641 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003642 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003643 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00003644 /*logger.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
Esin Karamanccb714b2019-11-29 15:02:06 +00003645 formulateSetFieldActionInfoFromFlow(field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003646 }
3647 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003648 } else if action.Type == flows.GROUP {
3649 formulateGroupActionInfoFromFlow(action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003650 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003651 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003652 }
3653 }
3654 return nil
3655}
3656
Esin Karamanccb714b2019-11-29 15:02:06 +00003657func formulateSetFieldActionInfoFromFlow(field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
3658 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003659 fieldtype := ofbField.GetType()
3660 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003661 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3662 actionInfo[VlanVid] = vlan & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00003663 logger.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003664 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303665 logger.Error("no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003666 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003667 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3668 pcp := ofbField.GetVlanPcp()
3669 actionInfo[VlanPcp] = pcp
3670 log.Debugw("action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003671 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003672 logger.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003673 }
3674 }
3675}
3676
3677func formulateGroupActionInfoFromFlow(action *ofp.OfpAction, actionInfo map[string]interface{}) {
3678 if action.GetGroup() == nil {
Shrey Baid26912972020-04-16 21:02:31 +05303679 logger.Warn("no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003680 } else {
3681 actionInfo[GroupID] = action.GetGroup().GroupId
Girish Kumar2ad402b2020-03-20 19:45:12 +00003682 logger.Debugw("action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003683 }
3684}
3685
salmansiddiqui7ac62132019-08-22 03:58:50 +00003686func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003687 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Shrey Baid26912972020-04-16 21:02:31 +05303688 logger.Debug("controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003689 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3690 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003691 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003692 classifierInfo[InPort] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303693 logger.Debugw("upstream-pon-to-controller-flow--inport-in-tunnelid",
3694 log.Fields{
3695 "newinport": classifierInfo[InPort].(uint32),
3696 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003697 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303698 return olterrors.NewErrNotFound("child-in-port",
3699 log.Fields{
3700 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3701 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003702 }
3703 }
3704 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303705 logger.Debug("non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003706 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003707 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003708 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003709 actionInfo[Output] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303710 logger.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid",
3711 log.Fields{
3712 "newoutport": actionInfo[Output].(uint32),
3713 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003714 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303715 return olterrors.NewErrNotFound("out-port",
3716 log.Fields{
3717 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3718 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003719 }
3720 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3721 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003722 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003723 classifierInfo[InPort] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303724 logger.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid",
3725 log.Fields{
3726 "newinport": actionInfo[Output].(uint32),
3727 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003728 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303729 return olterrors.NewErrNotFound("nni-port",
3730 log.Fields{
3731 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3732 "in-port": classifierInfo[InPort].(uint32),
3733 "out-port": actionInfo[Output].(uint32),
3734 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003735 }
3736 }
3737 }
3738 return nil
3739}
Gamze Abakafee36392019-10-03 11:17:24 +00003740
Chaitrashree G S90a17952019-11-14 21:51:21 -05003741func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003742 /* Metadata 8 bytes:
3743 Most Significant 2 Bytes = Inner VLAN
3744 Next 2 Bytes = Tech Profile ID(TPID)
3745 Least Significant 4 Bytes = Port ID
3746 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3747 subscriber related flows.
3748 */
3749 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
3750 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003751 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003752 }
3753 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003754 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003755}
3756
3757func appendUnique(slice []uint32, item uint32) []uint32 {
3758 for _, sliceElement := range slice {
3759 if sliceElement == item {
3760 return slice
3761 }
3762 }
3763 return append(slice, item)
3764}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303765
3766// getNniIntfID gets nni intf id from the flow classifier/action
3767func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
3768
3769 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3770 if portType == voltha.Port_PON_OLT {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003771 intfID, err := IntfIDFromNniPortNum(action[Output].(uint32))
3772 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003773 logger.Debugw("invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003774 log.Fields{
3775 "port-number": action[Output].(uint32),
3776 "error": err})
3777 return uint32(0), err
3778 }
Shrey Baid26912972020-04-16 21:02:31 +05303779 logger.Infow("output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303780 return intfID, nil
3781 } else if portType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003782 intfID, err := IntfIDFromNniPortNum(classifier[InPort].(uint32))
3783 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003784 logger.Debugw("invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003785 log.Fields{
3786 "port-number": action[Output].(uint32),
3787 "error": err})
3788 return uint32(0), err
3789 }
Shrey Baid26912972020-04-16 21:02:31 +05303790 logger.Infow("input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303791 return intfID, nil
3792 }
3793 return uint32(0), nil
3794}
3795
3796// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
npujarec5762e2020-01-01 14:08:48 +05303797func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003798
3799 f.onuGemInfoLock.Lock()
3800 defer f.onuGemInfoLock.Unlock()
3801
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303802 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
Matt Jeanneret1719a072019-12-20 14:50:14 -05003803 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303804 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003805 if lookupGemPort == gemPort {
Shrey Baid26912972020-04-16 21:02:31 +05303806 logger.Infow("pktin-key/value-found-in-cache--no-need-to-update-kv--assume-both-in-sync",
3807 log.Fields{
3808 "pktinkey": pktInkey,
3809 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003810 return
3811 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303812 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003813 f.packetInGemPort[pktInkey] = gemPort
3814
npujarec5762e2020-01-01 14:08:48 +05303815 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Shrey Baid26912972020-04-16 21:02:31 +05303816 logger.Infow("pktin-key-not-found-in-local-cache-value-is-different--updating-cache-and-kv-store",
3817 log.Fields{
3818 "pktinkey": pktInkey,
3819 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303820 return
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003821
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303822}
3823
3824// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303825func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003826
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003827 f.onuGemInfoLock.Lock()
3828 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003829
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303830 onugem := f.onuGemInfo[intfID]
3831 for idx, onu := range onugem {
3832 if onu.OnuID == onuID {
3833 for _, uni := range onu.UniPorts {
3834 if uni == portNum {
Shrey Baid26912972020-04-16 21:02:31 +05303835 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 +05303836 return
3837 }
3838 }
3839 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3840 f.onuGemInfo[intfID] = onugem
3841 }
3842 }
npujarec5762e2020-01-01 14:08:48 +05303843 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandolo60913ed2020-06-23 19:31:14 -07003844
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303845}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303846
npujarec5762e2020-01-01 14:08:48 +05303847func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3848 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303849 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303850 logger.Error("failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303851 return
3852 }
3853 for gem, FlowIDs := range flowIDsList {
3854 gemPK := gemPortKey{intf, uint32(gem)}
3855 f.flowsUsedByGemPort[gemPK] = FlowIDs
3856 }
3857 return
3858}
Esin Karamanccb714b2019-11-29 15:02:06 +00003859
3860//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
3861//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05303862func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
3863 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00003864 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303865 logger.Error("failed-to-get-pon-interface-to-multicast-queue-map")
Esin Karamanccb714b2019-11-29 15:02:06 +00003866 return
3867 }
3868 for intf, queueInfo := range storedMulticastQueueMap {
3869 q := queueInfoBrief{
3870 gemPortID: queueInfo[0],
3871 servicePriority: queueInfo[1],
3872 }
3873 f.interfaceToMcastQueueMap[intf] = &q
3874 }
3875}
3876
3877//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
3878//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
3879//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05303880func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
3881 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00003882 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003883 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00003884 }
3885 if exists {
3886 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
3887 }
3888 return nil, exists, nil
3889}
3890
3891func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
3892 groupDesc := ofp.OfpGroupDesc{
3893 Type: ofp.OfpGroupType_OFPGT_ALL,
3894 GroupId: groupID,
3895 }
3896 groupEntry := ofp.OfpGroupEntry{
3897 Desc: &groupDesc,
3898 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003899 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003900 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00003901 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003902 bucket := ofp.OfpBucket{
3903 Actions: acts,
3904 }
3905 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00003906 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003907 return &groupEntry
3908}