blob: 4a8df122f420bc27dfb5952e567aa229c0d52fb3 [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
202 tpInst *tp.TechProfile
203 meterID uint32
204 flowMetadata *voltha.FlowMetadata
205}
206
Esin Karamanccb714b2019-11-29 15:02:06 +0000207type queueInfoBrief struct {
208 gemPortID uint32
209 servicePriority uint32
210}
211
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700212//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530213type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000214 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000215 deviceHandler *DeviceHandler
216 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000217 onuIdsLock sync.RWMutex
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530218 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
219 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700220 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
221 onuGemInfo [][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache, indexed by IntfId
222 onuGemInfoLock []sync.RWMutex // lock by Pon Port
223 pendingFlowDelete sync.Map
Girish Gowdra3d633032019-12-10 16:37:05 +0530224 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Esin Karamanccb714b2019-11-29 15:02:06 +0000225 perUserFlowHandleLock *mapmutex.Mutex
226 interfaceToMcastQueueMap map[uint32]*queueInfoBrief /*pon interface -> multicast queue map. Required to assign GEM to a bucket during group population*/
manikkaraj kbf256be2019-03-25 00:13:48 +0530227}
228
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700229//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
npujarec5762e2020-01-01 14:08:48 +0530230func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
Shrey Baid26912972020-04-16 21:02:31 +0530231 logger.Infow("initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530232 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530233 var err error
234 var idx uint32
235
manikkaraj kbf256be2019-03-25 00:13:48 +0530236 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530237 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000238 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530239 if err = flowMgr.populateTechProfilePerPonPort(); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530240 logger.Errorw("error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530241 return nil
242 }
William Kurkian740a09c2019-10-23 17:07:38 -0400243 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530244 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
245 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530246 ponPorts := rMgr.DevInfo.GetPonPorts()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700247 flowMgr.onuGemInfo = make([][]rsrcMgr.OnuGemInfo, ponPorts)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530248 //Load the onugem info cache from kv store on flowmanager start
249 for idx = 0; idx < ponPorts; idx++ {
npujarec5762e2020-01-01 14:08:48 +0530250 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530251 logger.Error("failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530252 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530253 //Load flowID list per gem map per interface from the kvstore.
npujarec5762e2020-01-01 14:08:48 +0530254 flowMgr.loadFlowIDlistForGem(ctx, idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530255 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700256 flowMgr.onuGemInfoLock = make([]sync.RWMutex, ponPorts)
Girish Gowdra3d633032019-12-10 16:37:05 +0530257 flowMgr.pendingFlowDelete = sync.Map{}
Girish Gowdrab77ded92020-04-08 11:45:05 -0700258 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(300, 100000000, 10000000, 1.1, 0.2)
Esin Karamanccb714b2019-11-29 15:02:06 +0000259 flowMgr.interfaceToMcastQueueMap = make(map[uint32]*queueInfoBrief)
260 //load interface to multicast queue map from kv store
npujarec5762e2020-01-01 14:08:48 +0530261 flowMgr.loadInterfaceToMulticastQueueMap(ctx)
Shrey Baid26912972020-04-16 21:02:31 +0530262 logger.Info("initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530263 return &flowMgr
264}
265
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700266func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700267 if direction == Upstream {
Shrey Baid26912972020-04-16 21:02:31 +0530268 logger.Debugw("upstream-flow-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700269 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700270 } else if direction == Downstream {
Shrey Baid26912972020-04-16 21:02:31 +0530271 logger.Debugw("downstream-flow-not-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700272 return uint64(flowID), nil
Esin Karamanccb714b2019-11-29 15:02:06 +0000273 } else if direction == Multicast {
Shrey Baid26912972020-04-16 21:02:31 +0530274 logger.Debugw("multicast-flow-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000275 return 0x2<<15 | uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400276 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530277 return 0, olterrors.NewErrInvalidValue(log.Fields{"direction": direction}, nil).Log()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400278 }
279}
280
npujarec5762e2020-01-01 14:08:48 +0530281func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Shrey Baid26912972020-04-16 21:02:31 +0530282 logger.Debugw("registering-flow-for-device ",
283 log.Fields{
284 "flow": flowFromCore,
285 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000286 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
287 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
288 if !ok {
289 flowIDList = []uint32{deviceFlow.FlowId}
290 }
291 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
292 f.flowsUsedByGemPort[gemPK] = flowIDList
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530293 // update the flowids for a gem to the KVstore
npujarec5762e2020-01-01 14:08:48 +0530294 f.resourceMgr.UpdateFlowIDsForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400295}
296
npujarec5762e2020-01-01 14:08:48 +0530297func (f *OpenOltFlowMgr) divideAndAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000298 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
299 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000300 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530301 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400302 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530303
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700304 logger.Infow("dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530305 "device-id": f.deviceHandler.device.Id,
306 "intf-id": intfID,
307 "onu-id": onuID,
308 "uni-id": uniID,
309 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700310 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530311 "action": actionInfo,
312 "usmeter-iD": UsMeterID,
313 "dsmeter-iD": DsMeterID,
314 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400315 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
316 // is because the flow is an NNI flow and there would be no onu resources associated with it
317 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400318 if onuID <= 0 {
Shrey Baid26912972020-04-16 21:02:31 +0530319 logger.Errorw("no-onu-id-for-flow",
320 log.Fields{
321 "port-no": portNo,
322 "classifer": classifierInfo,
323 "action": actionInfo,
324 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530325 return
326 }
327
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700328 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Shrey Baid26912972020-04-16 21:02:31 +0530329 logger.Debugw("uni-port-path", log.Fields{
330 "uni": uni,
331 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530332
333 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
334 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700335 logger.Debugw("dividing-flow-create-tcont-gem-ports", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530336 "device-id": f.deviceHandler.device.Id,
337 "intf-id": intfID,
338 "onu-id": onuID,
339 "uni-id": uniID,
340 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700341 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530342 "action": actionInfo,
343 "usmeter-id": UsMeterID,
344 "dsmeter-id": DsMeterID,
345 "tp-id": TpID})
npujarec5762e2020-01-01 14:08:48 +0530346 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530347 if allocID == 0 || gemPorts == nil || TpInst == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000348 logger.Error("alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530349 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
350 return
351 }
352 args := make(map[string]uint32)
353 args[IntfID] = intfID
354 args[OnuID] = onuID
355 args[UniID] = uniID
356 args[PortNo] = portNo
357 args[AllocID] = allocID
358
359 /* Flows can be added specific to gemport if p-bits are received.
360 * If no pbit mentioned then adding flows for all gemports
361 */
npujarec5762e2020-01-01 14:08:48 +0530362 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530363 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
364 } else {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700365 logger.Errorw("failed-to-acquire-per-user-flow-handle-lock",
Shrey Baid26912972020-04-16 21:02:31 +0530366 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700367 "intf-id": intfID,
368 "onu-id": onuID,
369 "uni-id": uniID,
370 "flow-id": flow.Id,
371 "flow-cookie": flow.Cookie,
372 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400373 return
374 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530375}
376
salmansiddiqui7ac62132019-08-22 03:58:50 +0000377// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530378func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400379
Shrey Baid26912972020-04-16 21:02:31 +0530380 logger.Debugw("CreateSchedulerQueues",
381 log.Fields{"dir": sq.direction,
382 "intf-id": sq.intfID,
383 "onu-id": sq.onuID,
384 "uni-id": sq.uniID,
385 "tp-id": sq.tpID,
386 "meter-id": sq.meterID,
387 "tp-inst": sq.tpInst,
388 "flowmetadata": sq.flowMetadata,
389 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400390
Gamze Abakafee36392019-10-03 11:17:24 +0000391 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000392 if err != nil {
393 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400394 }
395
396 /* Lets make a simple assumption that if the meter-id is present on the KV store,
397 * then the scheduler and queues configuration is applied on the OLT device
398 * in the given direction.
399 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000400
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530402 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400403 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530404 return olterrors.NewErrNotFound("meter",
405 log.Fields{"intf-id": sq.intfID,
406 "onu-id": sq.onuID,
407 "uni-id": sq.uniID,
408 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400409 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000410
Manikkaraj kb1d51442019-07-23 10:41:02 -0400411 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000412 if KvStoreMeter.MeterId == sq.meterID {
Shrey Baid26912972020-04-16 21:02:31 +0530413 logger.Debugw("scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400414 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400415 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530416 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800417 "unsupported": "meter-id",
418 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530419 "meter-id-in-flow": sq.meterID,
420 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400421 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000422
Shrey Baid26912972020-04-16 21:02:31 +0530423 logger.Debugw("meter-does-not-exist-creating-new",
424 log.Fields{
425 "meter-id": sq.meterID,
426 "direction": Direction,
427 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000428
Gamze Abakafee36392019-10-03 11:17:24 +0000429 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000430 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Gamze Abakafee36392019-10-03 11:17:24 +0000431 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000432 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400433 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000434
435 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530436 return olterrors.NewErrNotFound("scheduler-config",
437 log.Fields{
438 "intf-id": sq.intfID,
439 "direction": sq.direction,
440 "tp-inst": sq.tpInst,
441 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000442 }
443
Manikkaraj kb1d51442019-07-23 10:41:02 -0400444 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000445 if sq.flowMetadata != nil {
446 for _, meter := range sq.flowMetadata.Meters {
447 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400448 meterConfig = meter
Shrey Baid26912972020-04-16 21:02:31 +0530449 logger.Debugw("found-meter-config-from-flowmetadata",
450 log.Fields{"meterConfig": meterConfig,
451 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400452 break
453 }
454 }
455 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530456 logger.Errorw("flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400457 }
458 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530459 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800460 "reason": "Could-not-get-meterbands-from-flowMetadata",
461 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530462 "meter-id": sq.meterID,
463 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400464 } else if len(meterConfig.Bands) < MaxMeterBand {
Shrey Baid26912972020-04-16 21:02:31 +0530465 logger.Errorw("invalid-number-of-bands-in-meter",
466 log.Fields{"Bands": meterConfig.Bands,
467 "meter-id": sq.meterID,
468 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530469 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800470 "reason": "Invalid-number-of-bands-in-meter",
471 "meterband-count": len(meterConfig.Bands),
472 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530473 "meter-id": sq.meterID,
474 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400475 }
476 cir := meterConfig.Bands[0].Rate
477 cbs := meterConfig.Bands[0].BurstSize
478 eir := meterConfig.Bands[1].Rate
479 ebs := meterConfig.Bands[1].BurstSize
480 pir := cir + eir
481 pbs := cbs + ebs
482 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
483
Gamze Abakafee36392019-10-03 11:17:24 +0000484 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000485 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400486
npujarec5762e2020-01-01 14:08:48 +0530487 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530488 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
489 log.Fields{"intf-id": sq.intfID,
490 "direction": sq.direction,
491 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400492 }
493
salmansiddiqui7ac62132019-08-22 03:58:50 +0000494 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400495 * store the meter id on the KV store, for further reference.
496 */
npujarec5762e2020-01-01 14:08:48 +0530497 if err := f.resourceMgr.UpdateMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530498 return olterrors.NewErrAdapter("failed-updating-meter-id",
499 log.Fields{"onu-id": sq.onuID,
500 "meter-id": sq.meterID,
501 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400502 }
Shrey Baid26912972020-04-16 21:02:31 +0530503 logger.Infow("updated-meter-info-into-kv-store-successfully",
504 log.Fields{"direction": Direction,
505 "Meter": meterConfig,
506 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400507 return nil
508}
509
npujarec5762e2020-01-01 14:08:48 +0530510func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000511
512 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
513
514 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530515 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
516 log.Fields{"intf-id": sq.intfID,
517 "direction": sq.direction,
518 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000519 }
520
Shrey Baid26912972020-04-16 21:02:31 +0530521 logger.Debugw("sending-traffic-scheduler-create-to-device",
522 log.Fields{
523 "direction": sq.direction,
524 "TrafficScheds": TrafficSched,
525 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530526 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000527 IntfId: sq.intfID, OnuId: sq.onuID,
528 UniId: sq.uniID, PortNo: sq.uniPort,
529 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000530 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000531 }
Shrey Baid26912972020-04-16 21:02:31 +0530532 logger.Infow("successfully-created-traffic-schedulers", log.Fields{
533 "direction": sq.direction,
534 "traffic-queues": trafficQueues,
535 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000536
537 // On receiving the CreateTrafficQueues request, the driver should create corresponding
538 // downstream queues.
Shrey Baid26912972020-04-16 21:02:31 +0530539 logger.Debugw("sending-traffic-queues-create-to-device",
540 log.Fields{"direction": sq.direction,
541 "traffic-queues": trafficQueues,
542 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530543 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000544 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
545 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000546 TrafficQueues: trafficQueues,
547 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530548 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000549 }
Shrey Baid26912972020-04-16 21:02:31 +0530550 logger.Infow("successfully-created-traffic-schedulers", log.Fields{
551 "direction": sq.direction,
552 "traffic-queues": trafficQueues,
553 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000554
Esin Karamanccb714b2019-11-29 15:02:06 +0000555 if sq.direction == tp_pb.Direction_DOWNSTREAM {
556 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(sq.tpInst)
557 if len(multicastTrafficQueues) > 0 {
558 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
559 //assumed that there is only one queue per PON for the multicast service
560 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
561 //just put it in interfaceToMcastQueueMap to use for building group members
Shrey Baid26912972020-04-16 21:02:31 +0530562 logger.Debugw("multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000563 multicastQueuePerPonPort := multicastTrafficQueues[0]
564 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
565 gemPortID: multicastQueuePerPonPort.GemportId,
566 servicePriority: multicastQueuePerPonPort.Priority,
567 }
568 //also store the queue info in kv store
npujarec5762e2020-01-01 14:08:48 +0530569 f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID,
Esin Karamanccb714b2019-11-29 15:02:06 +0000570 multicastQueuePerPonPort.GemportId,
571 multicastQueuePerPonPort.Priority)
Shrey Baid26912972020-04-16 21:02:31 +0530572
573 logger.Infow("multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000574 }
575 }
576 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000577 return nil
578}
579
salmansiddiqui7ac62132019-08-22 03:58:50 +0000580// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530581func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400582
583 var Direction string
584 var SchedCfg *tp_pb.SchedulerConfig
585 var err error
Shrey Baid26912972020-04-16 21:02:31 +0530586 logger.Infow("removing-schedulers-and-queues-in-olt",
587 log.Fields{
588 "direction": sq.direction,
589 "intf-id": sq.intfID,
590 "onu-id": sq.onuID,
591 "uni-id": sq.uniID,
592 "uni-port": sq.uniPort,
593 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000594 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000595 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400596 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000597 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000598 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400599 Direction = "downstream"
600 }
601
Girish Kumar8f73fe02019-12-09 13:19:37 +0000602 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530603 return olterrors.NewErrNotFound("scheduler-config",
604 log.Fields{
605 "int-id": sq.intfID,
606 "direction": sq.direction,
607 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000608 }
609
npujarec5762e2020-01-01 14:08:48 +0530610 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400611 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530612 return olterrors.NewErrNotFound("meter",
613 log.Fields{
614 "onu-id": sq.onuID,
615 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400616 }
617 if KVStoreMeter == nil {
Shrey Baid26912972020-04-16 21:02:31 +0530618 logger.Warnw("no-meter-installed-yet",
619 log.Fields{
620 "direction": Direction,
621 "intf-id": sq.intfID,
622 "onu-id": sq.onuID,
623 "uni-id": sq.uniID,
624 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400625 return nil
626 }
627 cir := KVStoreMeter.Bands[0].Rate
628 cbs := KVStoreMeter.Bands[0].BurstSize
629 eir := KVStoreMeter.Bands[1].Rate
630 ebs := KVStoreMeter.Bands[1].BurstSize
631 pir := cir + eir
632 pbs := cbs + ebs
633
634 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
635
Gamze Abakafee36392019-10-03 11:17:24 +0000636 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000637 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000638
639 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
640 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530641 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
642 log.Fields{
643 "intf-id": sq.intfID,
644 "direction": sq.direction,
645 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000646 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400647
npujarec5762e2020-01-01 14:08:48 +0530648 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000649 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
650 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000651 TrafficQueues: TrafficQueues,
652 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000653 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530654 log.Fields{
655 "intf-id": sq.intfID,
656 "traffic-queues": TrafficQueues,
657 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400658 }
Shrey Baid26912972020-04-16 21:02:31 +0530659 logger.Infow("removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530660 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000661 IntfId: sq.intfID, OnuId: sq.onuID,
662 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400663 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000664 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530665 log.Fields{
666 "intf-id": sq.intfID,
667 "traffic-schedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400668 }
669
Shrey Baid26912972020-04-16 21:02:31 +0530670 logger.Infow("removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000671
672 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400673 * delete the meter id on the KV store.
674 */
npujarec5762e2020-01-01 14:08:48 +0530675 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400676 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530677 return olterrors.NewErrAdapter("unable-to-remove-meter",
678 log.Fields{
679 "onu": sq.onuID,
680 "meter": KVStoreMeter.MeterId,
681 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400682 }
Shrey Baid26912972020-04-16 21:02:31 +0530683 logger.Infow("removed-meter-from-KV-store-successfully",
684 log.Fields{
685 "meter-id": KVStoreMeter.MeterId,
686 "dir": Direction,
687 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400688 return err
689}
690
Gamze Abakafee36392019-10-03 11:17:24 +0000691// This function allocates tconts and GEM ports for an ONU
npujarec5762e2020-01-01 14:08:48 +0530692func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) (uint32, []uint32, *tp.TechProfile) {
Gamze Abakafee36392019-10-03 11:17:24 +0000693 var allocIDs []uint32
694 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530695 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530696 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000697 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000698
npujarec5762e2020-01-01 14:08:48 +0530699 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
700 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400701
702 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530703
Shrey Baid26912972020-04-16 21:02:31 +0530704 logger.Debugw("creating-new-tcont-and-gem", log.Fields{
705 "intf-id": intfID,
706 "onu-id": onuID,
707 "uni-id": uniID,
708 "device-id": f.deviceHandler.device.Id,
709 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530710
Manikkaraj kb1d51442019-07-23 10:41:02 -0400711 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530712 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000713 if techProfileInstance == nil {
Shrey Baid26912972020-04-16 21:02:31 +0530714 logger.Infow("tp-instance-not-found--creating-new",
715 log.Fields{
716 "path": tpPath,
717 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530718 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000719 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530720 // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +0530721 logger.Errorw("tp-instance-create-failed",
722 log.Fields{
723 "error": err,
724 "tp-id": TpID,
725 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000726 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530727 }
npujarec5762e2020-01-01 14:08:48 +0530728 f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530729 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530730 logger.Debugw("tech-profile-instance-already-exist-for-given port-name",
731 log.Fields{
732 "uni": uni,
733 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530734 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530735 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400736 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000737 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
738 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530739 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530740 logger.Errorw("CreateSchedulerQueues-failed-upstream",
741 log.Fields{
742 "error": err,
743 "meter-id": UsMeterID,
744 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000745 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400746 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530747 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400748 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000749 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
750 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530751 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530752 logger.Errorw("CreateSchedulerQueues-failed-downstream",
753 log.Fields{
754 "error": err,
755 "meter-id": DsMeterID,
756 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000757 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400758 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530759 }
Gamze Abakafee36392019-10-03 11:17:24 +0000760
761 allocID := techProfileInstance.UsScheduler.AllocID
Gamze Abakafee36392019-10-03 11:17:24 +0000762 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Gamze Abakafee36392019-10-03 11:17:24 +0000763 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400764 }
Gamze Abakafee36392019-10-03 11:17:24 +0000765
Girish Gowdra3d633032019-12-10 16:37:05 +0530766 if tpInstanceExists {
767 return allocID, gemPortIDs, techProfileInstance
768 }
769
770 allocIDs = appendUnique(allocIDs, allocID)
771 for _, gemPortID := range gemPortIDs {
772 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
773 }
774
Shrey Baid26912972020-04-16 21:02:31 +0530775 logger.Infow("allocated-tcont-and-gem-ports",
776 log.Fields{
777 "alloc-ids": allocIDs,
778 "gemports": allgemPortIDs,
779 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530780 // Send Tconts and GEM ports to KV store
npujarec5762e2020-01-01 14:08:48 +0530781 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000782 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530783}
784
npujarec5762e2020-01-01 14:08:48 +0530785func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530786
Shrey Baid26912972020-04-16 21:02:31 +0530787 logger.Debugw("storing-allocated-tconts-and-gem-ports-into-KV-store",
788 log.Fields{
789 "intf-id": intfID,
790 "onu-id": onuID,
791 "uni-id": uniID,
792 "alloc-id": allocID,
793 "gemport-ids": gemPortIDs,
794 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530795 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530796 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530797 logger.Errorw("error-while-uploading-allocid-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530798 }
npujarec5762e2020-01-01 14:08:48 +0530799 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530800 logger.Errorw("error-while-uploading-gemports-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530801 }
npujarec5762e2020-01-01 14:08:48 +0530802 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530803 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 +0530804 }
Shrey Baid26912972020-04-16 21:02:31 +0530805 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 -0400806 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530807 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400808 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530809}
810
811func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000812 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530813 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000814 for _, intfID := range techRange.IntfIds {
815 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400816 tpCount++
Shrey Baid26912972020-04-16 21:02:31 +0530817 logger.Debugw("init-tech-profile-done",
818 log.Fields{
819 "intf-id": intfID,
820 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530821 }
822 }
823 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400824 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530825 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530826 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800827 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530828 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
829 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530830 }
Shrey Baid26912972020-04-16 21:02:31 +0530831 logger.Infow("populated-techprofile-for-ponports-successfully",
832 log.Fields{
833 "numofTech": tpCount,
834 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
835 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530836 return nil
837}
838
npujarec5762e2020-01-01 14:08:48 +0530839func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530840 portNo uint32, uplinkClassifier map[string]interface{},
841 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000842 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700843 uplinkClassifier[PacketTagType] = SingleTag
Shrey Baid26912972020-04-16 21:02:31 +0530844 logger.Debugw("adding-upstream-data-flow",
845 log.Fields{
846 "uplinkClassifier": uplinkClassifier,
847 "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800848 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000849 Upstream, logicalFlow, allocID, gemportID, tpID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530850 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530851}
852
npujarec5762e2020-01-01 14:08:48 +0530853func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530854 portNo uint32, downlinkClassifier map[string]interface{},
855 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000856 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700857 downlinkClassifier[PacketTagType] = DoubleTag
Shrey Baid26912972020-04-16 21:02:31 +0530858 logger.Debugw("adding-downstream-data-flow",
859 log.Fields{
860 "downlinkClassifier": downlinkClassifier,
861 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400862 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
863 if vlan, exists := downlinkClassifier[VlanVid]; exists {
864 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700865 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400866 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
Shrey Baid26912972020-04-16 21:02:31 +0530867 logger.Infow("ignoring-dl-trap-device-flow-from-core",
868 log.Fields{
869 "flow": logicalFlow,
870 "device-id": f.deviceHandler.device.Id,
871 "onu-id": onuID,
872 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800873 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400874 }
875 }
876 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530877 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400878
Manikkaraj k884c1242019-04-11 16:26:42 +0530879 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700880 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400881 // vlan_vid is a uint32. must be type asserted as such or conversion fails
882 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530883 if ok {
884 downlinkAction[VlanVid] = dlClVid & 0xfff
885 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530886 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530887 "reason": "failed-to-convert-vlanid-classifier",
888 "vlan-id": VlanVid,
889 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530890 }
891
David K. Bainbridge794735f2020-02-11 21:01:37 -0800892 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000893 Downstream, logicalFlow, allocID, gemportID, tpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530894}
895
npujarec5762e2020-01-01 14:08:48 +0530896func (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 +0530897 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000898 allocID uint32, gemPortID uint32, tpID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530899 /* One of the OLT platform (Broadcom BAL) requires that symmetric
900 flows require the same flow_id to be used across UL and DL.
901 Since HSIA flow is the only symmetric flow currently, we need to
902 re-use the flow_id across both direction. The 'flow_category'
903 takes priority over flow_cookie to find any available HSIA_FLOW
904 id for the ONU.
905 */
Shrey Baid26912972020-04-16 21:02:31 +0530906 logger.Infow("adding-hsia-flow",
907 log.Fields{
908 "intf-id": intfID,
909 "onu-id": onuID,
910 "uni-id": uniID,
911 "device-id": f.deviceHandler.device.Id,
912 "classifier": classifier,
913 "action": action,
914 "direction": direction,
915 "alloc-id": allocID,
916 "gemport-id": gemPortID,
917 "logicalflow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530918 var vlanPbit uint32 = 0xff // means no pbit
Gamze Abaka724d0852020-03-18 12:10:24 +0000919 var vlanVid uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400920 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000921 vlanPbit = classifier[VlanPcp].(uint32)
Shrey Baid26912972020-04-16 21:02:31 +0530922 logger.Debugw("found-pbit-in-flow",
923 log.Fields{
924 "vlan-pbit": vlanPbit,
925 "intf-id": intfID,
926 "onu-id": onuID,
927 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800928 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530929 logger.Debugw("pbit-not-found-in-flow",
930 log.Fields{
931 "vlan-pcp": VlanPcp,
932 "intf-id": intfID,
933 "onu-id": onuID,
934 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400935 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000936 if _, ok := classifier[VlanVid]; ok {
937 vlanVid = classifier[VlanVid].(uint32)
Shrey Baid26912972020-04-16 21:02:31 +0530938 log.Debugw("found-vlan-in-the-flow",
939 log.Fields{
940 "vlan-vid": vlanVid,
941 "intf-id": intfID,
942 "onu-id": onuID,
943 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000944 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700945 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530946 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +0530947 logger.Infow("flow-already-exists",
948 log.Fields{
949 "device-id": f.deviceHandler.device.Id,
950 "intf-id": intfID,
951 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800952 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530953 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000954 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530955 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530956 return olterrors.NewErrNotFound("hsia-flow-id",
957 log.Fields{
958 "direction": direction,
959 "device-id": f.deviceHandler.device.Id,
960 "intf-id": intfID,
961 "onu-id": onuID,
962 }, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530963 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800964 classifierProto, err := makeOpenOltClassifierField(classifier)
965 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530966 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530967 }
Shrey Baid26912972020-04-16 21:02:31 +0530968 logger.Debugw("created-classifier-proto",
969 log.Fields{
970 "classifier": *classifierProto,
971 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000972 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800973 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530974 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530975 }
Shrey Baid26912972020-04-16 21:02:31 +0530976 logger.Debugw("created-action-proto",
977 log.Fields{
978 "action": *actionProto,
979 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800980 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530981 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530982 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800983 log.Fields{
984 "classifier": classifier,
985 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +0530986 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800987 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530988 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700989 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
990 OnuId: int32(onuID),
991 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000992 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530993 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700994 AllocId: int32(allocID),
995 NetworkIntfId: int32(networkIntfID),
996 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530997 Classifier: classifierProto,
998 Action: actionProto,
999 Priority: int32(logicalFlow.Priority),
1000 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001001 PortNo: portNo,
1002 TechProfileId: tpID,
1003 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001004 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301005 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301006 }
Shrey Baid26912972020-04-16 21:02:31 +05301007 logger.Infow("hsia-flow-added-to-device-successfully",
1008 log.Fields{"direction": direction,
1009 "device-id": f.deviceHandler.device.Id,
1010 "flow": flow,
1011 "intf-id": intfID,
1012 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001013 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
1014 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1015 flow.OnuId,
1016 flow.UniId,
1017 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301018 return olterrors.NewErrPersistence("update", "flow", flowID,
1019 log.Fields{
1020 "flow": flow,
1021 "device-id": f.deviceHandler.device.Id,
1022 "intf-id": intfID,
1023 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001024 }
1025 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301026}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001027
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001028func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1029 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1030 gemPortID uint32, tpID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301031
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301032 networkIntfID, err := getNniIntfID(classifier, action)
1033 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301034 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001035 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301036 "action": action,
1037 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001038 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301039 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301040
1041 // Clear the action map
1042 for k := range action {
1043 delete(action, k)
1044 }
1045
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001046 action[TrapToHost] = true
1047 classifier[UDPSrc] = uint32(68)
1048 classifier[UDPDst] = uint32(67)
1049 classifier[PacketTagType] = SingleTag
1050 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301051
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001052 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301053 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301054 logger.Infow("flow-exists--not-re-adding",
1055 log.Fields{
1056 "device-id": f.deviceHandler.device.Id,
1057 "intf-id": intfID,
1058 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001059 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301060 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301061
David K. Bainbridge794735f2020-02-11 21:01:37 -08001062 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 +05301063
1064 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301065 return olterrors.NewErrNotFound("flow",
1066 log.Fields{
1067 "interface-id": intfID,
1068 "gem-port": gemPortID,
1069 "cookie": flowStoreCookie,
1070 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001071 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301072 }
1073
Shrey Baid26912972020-04-16 21:02:31 +05301074 logger.Debugw("creating-ul-dhcp-flow",
1075 log.Fields{
1076 "ul_classifier": classifier,
1077 "ul_action": action,
1078 "uplinkFlowId": flowID,
1079 "intf-id": intfID,
1080 "onu-id": onuID,
1081 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301082
David K. Bainbridge794735f2020-02-11 21:01:37 -08001083 classifierProto, err := makeOpenOltClassifierField(classifier)
1084 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301085 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301086 }
Shrey Baid26912972020-04-16 21:02:31 +05301087 logger.Debugw("created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001088 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001089 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301090 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301091 }
1092
David K. Bainbridge794735f2020-02-11 21:01:37 -08001093 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001094 OnuId: int32(onuID),
1095 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301096 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001097 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001098 AllocId: int32(allocID),
1099 NetworkIntfId: int32(networkIntfID),
1100 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301101 Classifier: classifierProto,
1102 Action: actionProto,
1103 Priority: int32(logicalFlow.Priority),
1104 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001105 PortNo: portNo,
1106 TechProfileId: tpID,
1107 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001108 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301109 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001110 }
Shrey Baid26912972020-04-16 21:02:31 +05301111 logger.Infow("dhcp-ul-flow-added-to-device-successfully",
1112 log.Fields{
1113 "device-id": f.deviceHandler.device.Id,
1114 "flow-id": flowID,
1115 "intf-id": intfID,
1116 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001117 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
1118 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
1119 dhcpFlow.OnuId,
1120 dhcpFlow.UniId,
1121 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301122 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1123 log.Fields{
1124 "flow": dhcpFlow,
1125 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301126 }
1127
David K. Bainbridge794735f2020-02-11 21:01:37 -08001128 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301129}
1130
Esin Karamanae41e2b2019-12-17 18:13:13 +00001131//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301132func (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 +00001133 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32) error {
1134 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001135}
1136
1137//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301138func (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 +00001139 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string, tpID uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001140
1141 networkIntfID, err := getNniIntfID(classifier, action)
1142 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301143 return olterrors.NewErrNotFound("nni-interface-id",
1144 log.Fields{
1145 "classifier": classifier,
1146 "action": action,
1147 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001148 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001149 }
1150
1151 // Clear the action map
1152 for k := range action {
1153 delete(action, k)
1154 }
1155
1156 action[TrapToHost] = true
1157 classifier[PacketTagType] = SingleTag
1158 delete(classifier, VlanVid)
1159
1160 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301161 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301162 logger.Infow("flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001163 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001164 }
1165
npujarec5762e2020-01-01 14:08:48 +05301166 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 +00001167
1168 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301169 return olterrors.NewErrNotFound("flow-id",
1170 log.Fields{
1171 "intf-id": intfID,
1172 "oni-id": onuID,
1173 "cookie": flowStoreCookie,
1174 "flow-type": flowType,
1175 "device-id": f.deviceHandler.device.Id,
1176 "onu-id": onuID},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001177 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001178 }
1179
Shrey Baid26912972020-04-16 21:02:31 +05301180 logger.Debugw("creating-upstream-trap-flow",
1181 log.Fields{
1182 "ul_classifier": classifier,
1183 "ul_action": action,
1184 "uplinkFlowId": flowID,
1185 "flowType": flowType,
1186 "device-id": f.deviceHandler.device.Id,
1187 "intf-id": intfID,
1188 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001189
David K. Bainbridge794735f2020-02-11 21:01:37 -08001190 classifierProto, err := makeOpenOltClassifierField(classifier)
1191 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301192 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001193 }
Shrey Baid26912972020-04-16 21:02:31 +05301194 logger.Debugw("created-classifier-proto",
1195 log.Fields{
1196 "classifier": *classifierProto,
1197 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001198 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001199 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301200 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001201 }
1202
David K. Bainbridge794735f2020-02-11 21:01:37 -08001203 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001204 OnuId: int32(onuID),
1205 UniId: int32(uniID),
1206 FlowId: flowID,
1207 FlowType: Upstream,
1208 AllocId: int32(allocID),
1209 NetworkIntfId: int32(networkIntfID),
1210 GemportId: int32(gemPortID),
1211 Classifier: classifierProto,
1212 Action: actionProto,
1213 Priority: int32(logicalFlow.Priority),
1214 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001215 PortNo: portNo,
1216 TechProfileId: tpID,
1217 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001218
David K. Bainbridge794735f2020-02-11 21:01:37 -08001219 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301220 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 -08001221 }
Shrey Baid26912972020-04-16 21:02:31 +05301222 logger.Infof("%s ul-flow-added-to-device-successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001223
David K. Bainbridge794735f2020-02-11 21:01:37 -08001224 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
1225 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1226 flow.OnuId,
1227 flow.UniId,
1228 flow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301229 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 +00001230 }
1231
David K. Bainbridge794735f2020-02-11 21:01:37 -08001232 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001233}
1234
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001235// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001236func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1237 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1238 gemPortID uint32, vlanID uint32, tpID uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05301239 logger.Infow("adding-eapol-to-device",
1240 log.Fields{
1241 "intf-id": intfID,
1242 "onu-id": onuID,
1243 "port-no": portNo,
1244 "alloc-id": allocID,
1245 "gemport-id": gemPortID,
1246 "vlan-id": vlanID,
1247 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301248
1249 uplinkClassifier := make(map[string]interface{})
1250 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301251
manikkaraj kbf256be2019-03-25 00:13:48 +05301252 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001253 uplinkClassifier[EthType] = uint32(EapEthType)
1254 uplinkClassifier[PacketTagType] = SingleTag
1255 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001256 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301257 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001258 uplinkAction[TrapToHost] = true
1259 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301260 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301261 logger.Infow("flow-exists-not-re-adding", log.Fields{
1262 "device-id": f.deviceHandler.device.Id,
1263 "onu-id": onuID,
1264 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001265 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301266 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301267 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +00001268 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +05301269 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301270 return olterrors.NewErrNotFound("flow-id",
1271 log.Fields{
1272 "intf-id": intfID,
1273 "onu-id": onuID,
1274 "coookie": flowStoreCookie,
1275 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001276 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301277 }
Shrey Baid26912972020-04-16 21:02:31 +05301278 logger.Debugw("creating-ul-eapol-flow",
1279 log.Fields{
1280 "ul_classifier": uplinkClassifier,
1281 "ul_action": uplinkAction,
1282 "uplinkFlowId": uplinkFlowID,
1283 "device-id": f.deviceHandler.device.Id,
1284 "intf-id": intfID,
1285 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301286
David K. Bainbridge794735f2020-02-11 21:01:37 -08001287 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1288 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301289 return olterrors.NewErrInvalidValue(log.Fields{
1290 "classifier": uplinkClassifier,
1291 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301292 }
Shrey Baid26912972020-04-16 21:02:31 +05301293 logger.Debugw("created-classifier-proto",
1294 log.Fields{
1295 "classifier": *classifierProto,
1296 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001297 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001298 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301299 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301300 }
Shrey Baid26912972020-04-16 21:02:31 +05301301 logger.Debugw("created-action-proto",
1302 log.Fields{
1303 "action": *actionProto,
1304 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001305 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301306 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301307 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001308 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301309 "action": action,
1310 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001311 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301312 }
1313
David K. Bainbridge794735f2020-02-11 21:01:37 -08001314 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001315 OnuId: int32(onuID),
1316 UniId: int32(uniID),
1317 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001318 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001319 AllocId: int32(allocID),
1320 NetworkIntfId: int32(networkIntfID),
1321 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301322 Classifier: classifierProto,
1323 Action: actionProto,
1324 Priority: int32(logicalFlow.Priority),
1325 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001326 PortNo: portNo,
1327 TechProfileId: tpID,
1328 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001329 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301330 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001331 }
Shrey Baid26912972020-04-16 21:02:31 +05301332 logger.Infow("eapol-ul-flow-added-to-device-successfully",
1333 log.Fields{
1334 "device-id": f.deviceHandler.device.Id,
1335 "onu-id": onuID,
1336 "intf-id": intfID,
1337 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001338 flowCategory := "EAPOL"
1339 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1340 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1341 upstreamFlow.OnuId,
1342 upstreamFlow.UniId,
1343 upstreamFlow.FlowId,
1344 /* lowCategory, */
1345 flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301346 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1347 log.Fields{
1348 "flow": upstreamFlow,
1349 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301350 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001351 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301352}
1353
David K. Bainbridge794735f2020-02-11 21:01:37 -08001354func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001355 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001356
1357 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1358 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1359 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001360 if vlanID != ReservedVlan {
1361 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001362 classifier.OVid = vid
1363 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301364 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001365 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1366 vid := uint32(metadata)
1367 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001368 classifier.IVid = vid
1369 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301370 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301371 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001372 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301373 classifier.OPbits = vlanPcp
1374 } else {
1375 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301376 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001377 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1378 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1379 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1380 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001381 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001382 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1383 classifier.PktTagType = pktTagType
1384
1385 switch pktTagType {
1386 case SingleTag:
1387 case DoubleTag:
1388 case Untagged:
1389 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001390 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301391 }
1392 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001393 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301394}
1395
Gamze Abaka724d0852020-03-18 12:10:24 +00001396func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001397 var actionCmd openoltpb2.ActionCmd
1398 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301399 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001400 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301401 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001402 if _, ok := actionInfo[VlanPcp]; ok {
1403 action.Cmd.RemarkInnerPbits = true
1404 action.IPbits = actionInfo[VlanPcp].(uint32)
1405 if _, ok := actionInfo[VlanVid]; ok {
1406 action.Cmd.TranslateInnerTag = true
1407 action.IVid = actionInfo[VlanVid].(uint32)
1408 }
1409 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001410 } else if _, ok := actionInfo[PushVlan]; ok {
1411 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301412 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001413 if _, ok := actionInfo[VlanPcp]; ok {
1414 action.OPbits = actionInfo[VlanPcp].(uint32)
1415 action.Cmd.RemarkOuterPbits = true
1416 if _, ok := classifierInfo[VlanVid]; ok {
1417 action.IVid = classifierInfo[VlanVid].(uint32)
1418 action.Cmd.TranslateInnerTag = true
1419 }
1420 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001421 } else if _, ok := actionInfo[TrapToHost]; ok {
1422 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301423 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001424 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301425 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001426 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301427}
1428
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001429// getTPpath return the ETCD path for a given UNI port
1430func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uniPath string, TpID uint32) string {
1431 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301432}
1433
Gamze Abakafee36392019-10-03 11:17:24 +00001434// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301435func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1436 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001437 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1438
Gamze Abakafee36392019-10-03 11:17:24 +00001439 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301440 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301441 olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301442 // return err
1443 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001444 }
Shrey Baid26912972020-04-16 21:02:31 +05301445 log.Debugw("tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001446 }
1447 return nil
1448}
1449
1450// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301451func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001452 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001453 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001454 }
npujarec5762e2020-01-01 14:08:48 +05301455 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301456 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1457 log.Fields{
1458 "tp-id": tpID,
1459 "uni-port-name": uniPortName,
1460 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001461 }
1462 return nil
1463}
1464
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001465func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301466 if len(classifier) == 0 { // should never happen
Shrey Baid26912972020-04-16 21:02:31 +05301467 logger.Error("invalid-classfier-object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301468 return 0
1469 }
Shrey Baid26912972020-04-16 21:02:31 +05301470 logger.Debugw("generating-flow-store-cookie",
1471 log.Fields{
1472 "classifier": classifier,
1473 "gemport-id": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301474 var jsonData []byte
1475 var flowString string
1476 var err error
1477 // TODO: Do we need to marshall ??
1478 if jsonData, err = json.Marshal(classifier); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301479 logger.Error("failed-to-encode-classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301480 return 0
1481 }
1482 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001483 if gemPortID != 0 {
1484 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301485 }
1486 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001487 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301488 hash := big.NewInt(0)
1489 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301490 generatedHash := hash.Uint64()
Shrey Baid26912972020-04-16 21:02:31 +05301491 logger.Debugw("hash-generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301492 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301493}
1494
npujarec5762e2020-01-01 14:08:48 +05301495func (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 +05301496 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001497 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001498 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1499 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1500 */
1501 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001502 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001503 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001504 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001505 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001506 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301507 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001508 if existingFlows != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301509 logger.Debugw("flow-exists-for-given-flowID--appending-it-to-current-flow",
1510 log.Fields{
1511 "flow-id": flow.FlowId,
1512 "device-id": f.deviceHandler.device.Id,
1513 "intf-id": intfID,
1514 "onu-id": flow.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001515 //for _, f := range *existingFlows {
1516 // flows = append(flows, f)
1517 //}
1518 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001519 }
Shrey Baid26912972020-04-16 21:02:31 +05301520 logger.Debugw("updated-flows-for-given-flowID-and-onuid",
1521 log.Fields{
1522 "updatedflow": flows,
1523 "flow-id": flow.FlowId,
1524 "onu-id": flow.OnuId,
1525 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +05301526 return &flows
1527}
1528
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001529//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1530// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1531// var intfId uint32
1532// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1533// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1534// */
1535// if flow.AccessIntfId != -1 {
1536// intfId = uint32(flow.AccessIntfId)
1537// } else {
1538// intfId = uint32(flow.NetworkIntfId)
1539// }
1540// // Get existing flows matching flowid for given subscriber from KV store
1541// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1542// if existingFlows != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001543// logger.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001544// for _, f := range *existingFlows {
1545// flows = append(flows, f)
1546// }
1547// }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001548// logger.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001549// return &flows
1550//}
1551
npujarec5762e2020-01-01 14:08:48 +05301552func (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 +05301553 logger.Debugw("storing-flow(s)-into-kv-store", log.Fields{
1554 "flow-id": flowID,
1555 "device-id": f.deviceHandler.device.Id,
1556 "intf-id": intfID,
1557 "onu-id": onuID})
npujarec5762e2020-01-01 14:08:48 +05301558 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301559 logger.Warnw("error-while-storing-flow-into-kv-store", log.Fields{
1560 "device-id": f.deviceHandler.device.Id,
1561 "onu-id": onuID,
1562 "intf-id": intfID,
1563 "flow-id": flowID})
manikkaraj k17652a72019-05-06 09:06:36 -04001564 return err
1565 }
Shrey Baid26912972020-04-16 21:02:31 +05301566 logger.Infow("stored-flow(s)-into-kv-store-successfully!", log.Fields{
1567 "device-id": f.deviceHandler.device.Id,
1568 "onu-id": onuID,
1569 "intf-id": intfID,
1570 "flow-id": flowID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301571 return nil
1572}
1573
David K. Bainbridge794735f2020-02-11 21:01:37 -08001574func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001575
1576 var intfID uint32
1577 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1578 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1579 */
1580 if deviceFlow.AccessIntfId != -1 {
1581 intfID = uint32(deviceFlow.AccessIntfId)
1582 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001583 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001584 intfID = uint32(deviceFlow.NetworkIntfId)
1585 }
1586
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001587 logger.Debugw("sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301588 "flow": *deviceFlow,
1589 "device-id": f.deviceHandler.device.Id,
1590 "intf-id": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301591 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001592
1593 st, _ := status.FromError(err)
1594 if st.Code() == codes.AlreadyExists {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001595 logger.Debug("flow-already-exists", log.Fields{
1596 "err": err,
1597 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301598 "device-id": f.deviceHandler.device.Id,
1599 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001600 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301601 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001602
1603 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301604 logger.Errorw("failed-to-add-flow-to-device",
1605 log.Fields{"err": err,
1606 "device-flow": deviceFlow,
1607 "device-id": f.deviceHandler.device.Id,
1608 "intf-id": intfID})
npujarec5762e2020-01-01 14:08:48 +05301609 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001610 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001611 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301612 if deviceFlow.GemportId != -1 {
1613 // No need to register the flow if it is a trap on nni flow.
npujarec5762e2020-01-01 14:08:48 +05301614 f.registerFlow(ctx, logicalFlow, deviceFlow)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301615 }
Shrey Baid26912972020-04-16 21:02:31 +05301616 logger.Infow("flow-added-to-device-successfully ",
1617 log.Fields{
1618 "flow": *deviceFlow,
1619 "device-id": f.deviceHandler.device.Id,
1620 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001621 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001622}
1623
Matteo Scandolo92186242020-06-12 10:54:18 -07001624func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
Shrey Baid26912972020-04-16 21:02:31 +05301625 logger.Debugw("sending-flow-to-device-via-grpc",
1626 log.Fields{
1627 "flow": *deviceFlow,
1628 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001629 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1630 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001631 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Shrey Baid26912972020-04-16 21:02:31 +05301632 logger.Warnw("can-not-remove-flow-from-device--unreachable",
1633 log.Fields{
1634 "err": err,
1635 "deviceFlow": deviceFlow,
1636 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001637 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001638 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001639 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001640 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001641
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001642 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001643 logger.Infow("flow-removed-from-device-successfully", log.Fields{
1644 "of-flow-id": ofFlowID,
1645 "flow": *deviceFlow,
1646 "device-id": f.deviceHandler.device.Id,
1647 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001648 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301649}
1650
1651/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1652 //update core flows_proxy : flows_proxy.update('/', flows)
1653}
1654
1655func generateStoredId(flowId uint32, direction string)uint32{
1656
David K. Bainbridge82efc492019-09-04 09:57:11 -07001657 if direction == Upstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001658 logger.Debug("Upstream flow shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301659 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001660 }else if direction == Downstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001661 logger.Debug("Downstream flow not shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301662 return flowId
1663 }else{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001664 logger.Errorw("Unrecognized direction",log.Fields{"direction": direction})
manikkaraj kbf256be2019-03-25 00:13:48 +05301665 return flowId
1666 }
1667}
1668
1669*/
1670
David K. Bainbridge794735f2020-02-11 21:01:37 -08001671func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001672
1673 classifierInfo := make(map[string]interface{})
1674 actionInfo := make(map[string]interface{})
1675
1676 classifierInfo[EthType] = uint32(LldpEthType)
1677 classifierInfo[PacketTagType] = Untagged
1678 actionInfo[TrapToHost] = true
1679
1680 // LLDP flow is installed to trap LLDP packets on the NNI port.
1681 // We manage flow_id resource pool on per PON port basis.
1682 // Since this situation is tricky, as a hack, we pass the NNI port
1683 // index (network_intf_id) as PON port Index for the flow_id resource
1684 // pool. Also, there is no ONU Id available for trapping LLDP packets
1685 // on NNI port, use onu_id as -1 (invalid)
1686 // ****************** CAVEAT *******************
1687 // This logic works if the NNI Port Id falls within the same valid
1688 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1689 // we need to have a re-look at this.
1690 // *********************************************
1691
1692 var onuID = -1
1693 var uniID = -1
1694 var gemPortID = -1
1695
David K. Bainbridge794735f2020-02-11 21:01:37 -08001696 networkInterfaceID, err := IntfIDFromNniPortNum(portNo)
1697 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301698 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001699 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001700 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301701 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301702 logger.Infow("flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001703 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001704 }
npujarec5762e2020-01-01 14:08:48 +05301705 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001706
1707 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301708 return olterrors.NewErrNotFound("flow-id",
1709 log.Fields{
1710 "interface-id": networkInterfaceID,
1711 "onu-id": onuID,
1712 "uni-id": uniID,
1713 "gem-port-id": gemPortID,
1714 "cookie": flowStoreCookie,
1715 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001716 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001717 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001718 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1719 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301720 return olterrors.NewErrInvalidValue(
1721 log.Fields{
1722 "classifier": classifierInfo,
1723 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001724 }
Shrey Baid26912972020-04-16 21:02:31 +05301725 logger.Debugw("created-classifier-proto",
1726 log.Fields{
1727 "classifier": *classifierProto,
1728 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001729 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001730 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301731 return olterrors.NewErrInvalidValue(
1732 log.Fields{
1733 "action": actionInfo,
1734 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001735 }
Shrey Baid26912972020-04-16 21:02:31 +05301736 logger.Debugw("created-action-proto",
1737 log.Fields{
1738 "action": *actionProto,
1739 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001740
1741 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1742 OnuId: int32(onuID), // OnuId not required
1743 UniId: int32(uniID), // UniId not used
1744 FlowId: flowID,
1745 FlowType: Downstream,
1746 NetworkIntfId: int32(networkInterfaceID),
1747 GemportId: int32(gemPortID),
1748 Classifier: classifierProto,
1749 Action: actionProto,
1750 Priority: int32(flow.Priority),
1751 Cookie: flow.Cookie,
1752 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001753 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301754 return olterrors.NewErrFlowOp("add", flowID,
1755 log.Fields{
1756 "flow": downstreamflow,
1757 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001758 }
Shrey Baid26912972020-04-16 21:02:31 +05301759 logger.Infow("lldp-trap-on-nni-flow-added-to-device-successfully",
1760 log.Fields{
1761 "device-id": f.deviceHandler.device.Id,
1762 "onu-id": onuID,
1763 "flow-id": flowID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001764 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1765 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1766 int32(onuID),
1767 int32(uniID),
1768 flowID, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301769 return olterrors.NewErrPersistence("update", "flow", flowID,
1770 log.Fields{
1771 "flow": downstreamflow,
1772 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001773 }
1774 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301775}
1776
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001777func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1778 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001779}
1780
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001781//getOnuDevice to fetch onu from cache or core.
1782func (f *OpenOltFlowMgr) getOnuDevice(intfID uint32, onuID uint32) (*OnuDevice, error) {
1783 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1784 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1785 if !ok {
Shrey Baid26912972020-04-16 21:02:31 +05301786 logger.Debugw("couldnt-find-onu-in-cache",
1787 log.Fields{
1788 "intf-id": intfID,
1789 "onu-id": onuID,
1790 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001791 onuDevice, err := f.getChildDevice(intfID, onuID)
1792 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301793 return nil, olterrors.NewErrNotFound("onu-child-device",
1794 log.Fields{
1795 "onu-id": onuID,
1796 "intf-id": intfID,
1797 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001798 }
1799 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1800 //better to ad the device to cache here.
1801 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1802 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301803 logger.Debugw("found-onu-in-cache",
1804 log.Fields{
1805 "intf-id": intfID,
1806 "onu-id": onuID,
1807 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001808 }
1809
1810 return onuDev.(*OnuDevice), nil
1811}
1812
1813//getChildDevice to fetch onu
1814func (f *OpenOltFlowMgr) getChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
Shrey Baid26912972020-04-16 21:02:31 +05301815 logger.Infow("GetChildDevice",
1816 log.Fields{
1817 "pon-port": intfID,
1818 "onu-id": onuID,
1819 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001820 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001821 onuDevice, err := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
1822 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301823 return nil, olterrors.NewErrNotFound("onu",
1824 log.Fields{
1825 "interface-id": parentPortNo,
1826 "onu-id": onuID,
1827 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001828 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301829 }
Shrey Baid26912972020-04-16 21:02:31 +05301830 logger.Infow("successfully-received-child-device-from-core",
1831 log.Fields{
1832 "device-id": f.deviceHandler.device.Id,
1833 "child_device_id": onuDevice.Id,
1834 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301835 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301836}
1837
1838func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Shrey Baid26912972020-04-16 21:02:31 +05301839 logger.Info("unimplemented-flow %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301840 return nil
1841}
1842
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001843func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
Shrey Baid26912972020-04-16 21:02:31 +05301844 logger.Info("unimplemented-device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301845}
1846
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001847func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001848 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001849 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001850 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001851 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001852}
1853
Girish Gowdra6b130582019-11-20 16:45:20 +05301854func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001855 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301856 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301857 logger.Debugw("couldnt-find-onu-child-device",
1858 log.Fields{
1859 "intf-id": intfID,
1860 "onu-id": onuID,
1861 "uni-id": uniID,
1862 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001863 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301864 }
1865
1866 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Shrey Baid26912972020-04-16 21:02:31 +05301867 logger.Debugw("sending-gem-port-delete-to-openonu-adapter",
1868 log.Fields{
1869 "msg": *delGemPortMsg,
1870 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301871 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1872 delGemPortMsg,
1873 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301874 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001875 onuDev.deviceType,
1876 onuDev.deviceID,
1877 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301878 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1879 log.Fields{
1880 "from-adapter": f.deviceHandler.device.Type,
1881 "to-adapter": onuDev.deviceType,
1882 "onu-id": onuDev.deviceID,
1883 "proxyDeviceID": onuDev.proxyDeviceID,
1884 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301885 }
Shrey Baid26912972020-04-16 21:02:31 +05301886 logger.Infow("success-sending-del-gem-port-to-onu-adapter",
1887 log.Fields{
1888 "msg": delGemPortMsg,
1889 "from-adapter": f.deviceHandler.device.Type,
1890 "to-adapter": onuDev.deviceType,
1891 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301892 return nil
1893}
1894
1895func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001896 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301897 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301898 logger.Warnw("couldnt-find-onu-child-device",
1899 log.Fields{
1900 "intf-id": intfID,
1901 "onu-id": onuID,
1902 "uni-id": uniID,
1903 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001904 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301905 }
1906
1907 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Shrey Baid26912972020-04-16 21:02:31 +05301908 logger.Debugw("sending-tcont-delete-to-openonu-adapter",
1909 log.Fields{
1910 "msg": *delTcontMsg,
1911 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301912 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1913 delTcontMsg,
1914 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301915 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001916 onuDev.deviceType,
1917 onuDev.deviceID,
1918 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301919 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1920 log.Fields{
1921 "from-adapter": f.deviceHandler.device.Type,
1922 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1923 "proxyDeviceID": onuDev.proxyDeviceID,
1924 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301925 }
Shrey Baid26912972020-04-16 21:02:31 +05301926 logger.Infow("success-sending-del-tcont-to-onu-adapter",
1927 log.Fields{
1928 "msg": delTcontMsg,
1929 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301930 return nil
1931}
1932
Girish Gowdra3d633032019-12-10 16:37:05 +05301933func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1934 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1935 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1936 if val.(int) > 0 {
1937 pnFlDels := val.(int) - 1
1938 if pnFlDels > 0 {
Shrey Baid26912972020-04-16 21:02:31 +05301939 logger.Debugw("flow-delete-succeeded--more-pending",
1940 log.Fields{
1941 "intf": Intf,
1942 "onu-id": onuID,
1943 "uni-id": uniID,
1944 "currpendingflowcnt": pnFlDels,
1945 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301946 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1947 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301948 logger.Debugw("all-pending-flow-deletes-handled--removing-entry-from-map",
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 f.pendingFlowDelete.Delete(pnFlDelKey)
1955 }
1956 }
1957 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301958 logger.Debugw("no-pending-delete-flows-found",
1959 log.Fields{
1960 "intf": Intf,
1961 "onu-id": onuID,
1962 "uni-id": uniID,
1963 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301964
1965 }
1966
1967}
1968
Girish Gowdrac3037402020-01-22 20:29:53 +05301969// Once the gemport is released for a given onu, it also has to be cleared from local cache
1970// which was used for deriving the gemport->logicalPortNo during packet-in.
1971// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1972// is conveyed to ONOS during packet-in OF message.
1973func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001974
1975 f.onuGemInfoLock[intfID].Lock()
1976 defer f.onuGemInfoLock[intfID].Unlock()
1977
Shrey Baid26912972020-04-16 21:02:31 +05301978 logger.Infow("deleting-gem-from-local-cache",
1979 log.Fields{
1980 "gem": gemPortID,
1981 "intf-id": intfID,
1982 "onu-id": onuID,
1983 "device-id": f.deviceHandler.device.Id,
1984 "onu-gem": f.onuGemInfo[intfID]})
Girish Gowdrac3037402020-01-22 20:29:53 +05301985 onugem := f.onuGemInfo[intfID]
serkant.uluderya96af4932020-02-20 16:58:48 -08001986 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301987 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001988 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301989 // If the gemport is found, delete it from local cache.
1990 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001991 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1992 onugem[i] = onu
Shrey Baid26912972020-04-16 21:02:31 +05301993 logger.Infow("removed-gemport-from-local-cache",
1994 log.Fields{
1995 "intf-id": intfID,
1996 "onu-id": onuID,
1997 "deletedgemport-id": gemPortID,
1998 "gemports": onu.GemPorts,
1999 "device-id": f.deviceHandler.device.Id})
Girish Gowdrac3037402020-01-22 20:29:53 +05302000 break
2001 }
2002 }
2003 break
2004 }
2005 }
2006}
2007
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302008//clearResources clears pon resources in kv store and the device
npujarec5762e2020-01-01 14:08:48 +05302009func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302010 gemPortID int32, flowID uint32, flowDirection string,
2011 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002012
Chaitrashree G S90a17952019-11-14 21:51:21 -05002013 tpID, err := getTpIDFromFlow(flow)
2014 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302015 return olterrors.NewErrNotFound("tp-id",
2016 log.Fields{
2017 "flow": flow,
2018 "intf": Intf,
2019 "onu-id": onuID,
2020 "uni-id": uniID,
2021 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002022 }
Gamze Abakafee36392019-10-03 11:17:24 +00002023
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002024 if len(updatedFlows) >= 0 {
2025 // There are still flows referencing the same flow_id.
2026 // So the flow should not be freed yet.
2027 // For ex: Case of HSIA where same flow is shared
2028 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00002029 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302030 olterrors.NewErrPersistence("update", "flow", flowID,
2031 log.Fields{
2032 "flow": updatedFlows,
2033 "device-id": f.deviceHandler.device.Id}, err).Log()
Girish Kumarf26e4882020-03-05 06:49:10 +00002034 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002035 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05302036 // Do this for subscriber flows only (not trap from NNI flows)
2037 if onuID != -1 && uniID != -1 {
2038 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
2039 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Shrey Baid26912972020-04-16 21:02:31 +05302040 logger.Debugw("creating-entry-for-pending-flow-delete",
2041 log.Fields{
2042 "flow-id": flowID,
2043 "intf": Intf,
2044 "onu-id": onuID,
2045 "uni-id": uniID,
2046 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302047 f.pendingFlowDelete.Store(pnFlDelKey, 1)
2048 } else {
2049 pnFlDels := val.(int) + 1
Shrey Baid26912972020-04-16 21:02:31 +05302050 logger.Debugw("updating-flow-delete-entry",
2051 log.Fields{
2052 "flow-id": flowID,
2053 "intf": Intf,
2054 "onu-id": onuID,
2055 "uni-id": uniID,
2056 "currPendingFlowCnt": pnFlDels,
2057 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302058 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
2059 }
2060
2061 defer f.deletePendingFlows(Intf, onuID, uniID)
2062 }
2063
Shrey Baid26912972020-04-16 21:02:31 +05302064 logger.Debugw("releasing-flow-id-to-resource-manager",
2065 log.Fields{
2066 "Intf": Intf,
2067 "onu-id": onuID,
2068 "uni-id": uniID,
2069 "flow-id": flowID,
2070 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302071 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002072
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002073 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302074 tpPath := f.getTPpath(Intf, uni, tpID)
Shrey Baid26912972020-04-16 21:02:31 +05302075 logger.Debugw("getting-techprofile-instance-for-subscriber",
2076 log.Fields{
2077 "TP-PATH": tpPath,
2078 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302079 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00002080 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +05302081 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
2082 log.Fields{
2083 "tp-id": tpID,
2084 "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002085 }
2086
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302087 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00002088 if f.isGemPortUsedByAnotherFlow(gemPK) {
2089 flowIDs := f.flowsUsedByGemPort[gemPK]
2090 for i, flowIDinMap := range flowIDs {
2091 if flowIDinMap == flowID {
2092 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302093 // everytime flowsUsedByGemPort cache is updated the same should be updated
2094 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002095 f.flowsUsedByGemPort[gemPK] = flowIDs
npujarec5762e2020-01-01 14:08:48 +05302096 f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00002097 break
2098 }
2099 }
Shrey Baid26912972020-04-16 21:02:31 +05302100 logger.Debugw("gem-port-id-is-still-used-by-other-flows",
2101 log.Fields{
2102 "gemport-id": gemPortID,
2103 "usedByFlows": flowIDs,
2104 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302105 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00002106 }
Shrey Baid26912972020-04-16 21:02:31 +05302107 logger.Debugf("gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05302108 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002109 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
2110 // 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 +05302111 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Girish Gowdrac3037402020-01-22 20:29:53 +05302112 f.deleteGemPortFromLocalCache(Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002113 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302114 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
2115 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002116 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05302117 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
2118 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002119 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05302120 // Delete the gem port on the ONU.
2121 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302122 logger.Errorw("error-processing-delete-gem-port-towards-onu",
2123 log.Fields{
2124 "err": err,
2125 "intf": Intf,
2126 "onu-id": onuID,
2127 "uni-id": uniID,
2128 "device-id": f.deviceHandler.device.Id,
2129 "gemport-id": gemPortID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302130 }
Gamze Abakafee36392019-10-03 11:17:24 +00002131
npujarec5762e2020-01-01 14:08:48 +05302132 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002133 if !ok {
npujarec5762e2020-01-01 14:08:48 +05302134 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
2135 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
2136 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
2137 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
2138 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302139 // Delete the TCONT on the ONU.
2140 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302141 logger.Errorw("error-processing-delete-tcont-towards-onu",
2142 log.Fields{
2143 "intf": Intf,
2144 "onu-id": onuID,
2145 "uni-id": uniID,
2146 "device-id": f.deviceHandler.device.Id,
2147 "alloc-id": techprofileInst.UsScheduler.AllocID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302148 }
Gamze Abakafee36392019-10-03 11:17:24 +00002149 }
2150 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002151 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302152 return nil
2153}
2154
David K. Bainbridge794735f2020-02-11 21:01:37 -08002155// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302156func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302157
Shrey Baid26912972020-04-16 21:02:31 +05302158 logger.Infow("clear-flow-from-resource-manager",
2159 log.Fields{
2160 "flowDirection": flowDirection,
2161 "flow": *flow,
2162 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002163
2164 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05302165 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002166 return
2167 }
2168
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302169 var updatedFlows []rsrcMgr.FlowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302170 classifierInfo := make(map[string]interface{})
2171
2172 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
2173 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002174 logger.Error(err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302175 return
2176 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302177
David K. Bainbridge794735f2020-02-11 21:01:37 -08002178 onuID := int32(onu)
2179 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302180
2181 for _, field := range flows.GetOfbFields(flow) {
2182 if field.Type == flows.IP_PROTO {
2183 classifierInfo[IPProto] = field.GetIpProto()
Shrey Baid26912972020-04-16 21:02:31 +05302184 logger.Debugw("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302185 }
2186 }
Shrey Baid26912972020-04-16 21:02:31 +05302187 logger.Infow("extracted-access-info-from-flow-to-be-deleted",
2188 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002189 "flow-id": flow.Id,
2190 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302191 "onu-id": onuID,
2192 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302193
2194 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2195 onuID = -1
2196 uniID = -1
Shrey Baid26912972020-04-16 21:02:31 +05302197 logger.Debug("trap-on-nni-flow-set-oni--uni-to- -1")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002198 Intf, err = IntfIDFromNniPortNum(inPort)
2199 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002200 logger.Errorw("invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002201 log.Fields{
2202 "port-number": inPort,
2203 "error": err})
2204 return
2205 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302206 }
npujarec5762e2020-01-01 14:08:48 +05302207 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002208 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302209 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302210 if flowInfo == nil {
Shrey Baid26912972020-04-16 21:02:31 +05302211 logger.Debugw("no-flowinfo-found-in-kv-store",
2212 log.Fields{
2213 "intf": Intf,
2214 "onu-id": onuID,
2215 "uni-id": uniID,
2216 "flow-id": flowID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302217 return
2218 }
2219 updatedFlows = nil
2220 for _, flow := range *flowInfo {
2221 updatedFlows = append(updatedFlows, flow)
2222 }
2223
2224 for i, storedFlow := range updatedFlows {
2225 if flow.Id == storedFlow.LogicalFlowID {
2226 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Shrey Baid26912972020-04-16 21:02:31 +05302227 logger.Debugw("flow-to-be-deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002228 // DKB
Matteo Scandolo92186242020-06-12 10:54:18 -07002229 if err = f.removeFlowFromDevice(&removeFlowMessage, flow.Id); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002230 logger.Errorw("failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002231 return
2232 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002233 logger.Info("flow-removed-from-device-successfully", log.Fields{
2234 "flow-id": flow.Id,
2235 "stored-flow": storedFlow,
2236 "device-id": f.deviceHandler.device.Id,
2237 "stored-flow-id": flowID,
2238 "onu-id": onuID,
2239 "intf": Intf,
2240 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08002241 //Remove the Flow from FlowInfo
2242 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
2243 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
2244 flowID, flowDirection, portNum, updatedFlows); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07002245 logger.Error("failed-to-clear-resources-for-flow", 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 })
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302253 return
2254 }
2255 }
2256 }
2257 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002258}
2259
Esin Karamanccb714b2019-11-29 15:02:06 +00002260//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
2261// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05302262func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002263 classifierInfo := make(map[string]interface{})
2264 formulateClassifierInfoFromFlow(classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00002265 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002266
2267 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302268 logger.Warnw("no-inport-found--cannot-release-resources-of-the-multicast-flow", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002269 return
2270 }
2271
Esin Karamanccb714b2019-11-29 15:02:06 +00002272 var onuID = int32(NoneOnuID)
2273 var uniID = int32(NoneUniID)
2274 var flowID uint32
2275 var updatedFlows []rsrcMgr.FlowInfo
2276
npujarec5762e2020-01-01 14:08:48 +05302277 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002278
2279 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302280 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002281 if flowInfo == nil {
Shrey Baid26912972020-04-16 21:02:31 +05302282 logger.Debugw("no-multicast-flowinfo-found-in-the-kv-store",
2283 log.Fields{
2284 "intf": networkInterfaceID,
2285 "onu-id": onuID,
2286 "uni-id": uniID,
2287 "flow-id": flowID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002288 continue
2289 }
2290 updatedFlows = nil
2291 for _, flow := range *flowInfo {
2292 updatedFlows = append(updatedFlows, flow)
2293 }
2294 for i, storedFlow := range updatedFlows {
2295 if flow.Id == storedFlow.LogicalFlowID {
2296 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Shrey Baid26912972020-04-16 21:02:31 +05302297 logger.Debugw("multicast-flow-to-be-deleted",
2298 log.Fields{
2299 "flow": storedFlow,
2300 "flow-id": flow.Id,
2301 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002302 //remove from device
Matteo Scandolo92186242020-06-12 10:54:18 -07002303 if err := f.removeFlowFromDevice(&removeFlowMessage, flow.Id); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002304 // DKB
Girish Kumar2ad402b2020-03-20 19:45:12 +00002305 logger.Errorw("failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002306 log.Fields{
2307 "flow-id": flow.Id,
2308 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002309 return
2310 }
Shrey Baid26912972020-04-16 21:02:31 +05302311 logger.Infow("multicast-flow-removed-from-device-successfully", log.Fields{"flow-id": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002312 //Remove the Flow from FlowInfo
2313 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05302314 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302315 logger.Errorw("failed-to-delete-multicast-flow-from-the-kv-store",
2316 log.Fields{"flow": storedFlow,
2317 "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002318 return
2319 }
2320 //release flow id
Shrey Baid26912972020-04-16 21:02:31 +05302321 logger.Debugw("releasing-multicast-flow-id",
2322 log.Fields{"flow-id": flowID,
2323 "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05302324 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002325 }
2326 }
2327 }
2328}
2329
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002330//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002331func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002332 logger.Infow("removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302333 var direction string
2334 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002335
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302336 for _, action := range flows.GetActions(flow) {
2337 if action.Type == flows.OUTPUT {
2338 if out := action.GetOutput(); out != nil {
2339 actionInfo[Output] = out.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002340 logger.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302341 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302342 logger.Error("invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002343 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002344 }
2345 }
2346 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002347
2348 if flows.HasGroup(flow) {
2349 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07002350 f.clearFlowFromResourceManager(ctx, flow, direction)
2351 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002352 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302353 direction = Upstream
2354 } else {
2355 direction = Downstream
2356 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302357
Girish Gowdracefae192020-03-19 18:14:10 -07002358 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(flow, direction)
2359 if err != nil {
2360 return err
2361 }
2362
2363 userKey := tpLockKey{intfID, onuID, uniID}
2364
2365 // Serialize flow removes on a per subscriber basis
2366 if f.perUserFlowHandleLock.TryLock(userKey) {
2367 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
2368 f.perUserFlowHandleLock.Unlock(userKey)
2369 } else {
2370 // Ideally this should never happen
Shrey Baid26912972020-04-16 21:02:31 +05302371 logger.Errorw("failed-to-acquire-lock-to-remove-flow--remove-aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07002372 return errors.New("failed-to-acquire-per-user-lock")
2373 }
2374
2375 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002376}
2377
Girish Gowdra3d633032019-12-10 16:37:05 +05302378func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
2379 uniID uint32, ch chan bool) {
2380 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2381 for {
2382 select {
2383 case <-time.After(20 * time.Millisecond):
2384 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Shrey Baid26912972020-04-16 21:02:31 +05302385 logger.Debug("pending-flow-deletes-completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05302386 ch <- true
2387 return
2388 }
2389 case <-ctx.Done():
Shrey Baid26912972020-04-16 21:02:31 +05302390 logger.Error("flow-delete-wait-handler-routine-canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05302391 return
2392 }
2393 }
2394}
2395
Esin Karamanae41e2b2019-12-17 18:13:13 +00002396//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2397func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2398 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2399 if ethType, ok := classifierInfo[EthType]; ok {
2400 if ethType.(uint32) == IPv4EthType {
2401 if ipProto, ok := classifierInfo[IPProto]; ok {
2402 if ipProto.(uint32) == IgmpProto {
2403 return true
2404 }
2405 }
2406 }
2407 }
2408 }
2409 return false
2410}
2411
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002412// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302413// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002414func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002415 classifierInfo := make(map[string]interface{})
2416 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002417 var UsMeterID uint32
2418 var DsMeterID uint32
2419
Shrey Baid26912972020-04-16 21:02:31 +05302420 logger.Infow("adding-flow",
2421 log.Fields{
2422 "flow": flow,
2423 "flowmetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002424 formulateClassifierInfoFromFlow(classifierInfo, flow)
2425
2426 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
2427 if err != nil {
2428 // Error logging is already done in the called function
2429 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002430 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302431 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002432
Esin Karamanccb714b2019-11-29 15:02:06 +00002433 if flows.HasGroup(flow) {
2434 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002435 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002436 }
2437
manikkaraj k17652a72019-05-06 09:06:36 -04002438 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00002439 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
2440 if err != nil {
2441 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002442 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002443 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002444
Shrey Baid26912972020-04-16 21:02:31 +05302445 logger.Debugw("flow-ports",
2446 log.Fields{
2447 "classifierinfo_inport": classifierInfo[InPort],
2448 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002449 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002450
Humera Kouser94d7a842019-08-25 19:04:32 -04002451 if ethType, ok := classifierInfo[EthType]; ok {
2452 if ethType.(uint32) == LldpEthType {
Shrey Baid26912972020-04-16 21:02:31 +05302453 logger.Info("adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002454 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002455 }
2456 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002457 if ipProto, ok := classifierInfo[IPProto]; ok {
2458 if ipProto.(uint32) == IPProtoDhcp {
2459 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302460 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002461 logger.Debug("trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002462 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002463 }
2464 }
2465 }
2466 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002467 if isIgmpTrapDownstreamFlow(classifierInfo) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002468 logger.Debug("trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002469 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002470 }
A R Karthick1f85b802019-10-11 05:06:05 +00002471
2472 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
npujarec5762e2020-01-01 14:08:48 +05302473 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002474
Chaitrashree G S90a17952019-11-14 21:51:21 -05002475 TpID, err := getTpIDFromFlow(flow)
2476 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302477 return olterrors.NewErrNotFound("tpid-for-flow",
2478 log.Fields{
2479 "flow": flow,
2480 "intf-id": IntfID,
2481 "onu-id": onuID,
2482 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002483 }
Shrey Baid26912972020-04-16 21:02:31 +05302484 logger.Debugw("tpid-for-this-subcriber",
2485 log.Fields{
2486 "tp-id": TpID,
2487 "intf-id": intfID,
2488 "onu-id": onuID,
2489 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002490 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002491 UsMeterID = flows.GetMeterIdFromFlow(flow)
Shrey Baid26912972020-04-16 21:02:31 +05302492 logger.Debugw("upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002493 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002494 DsMeterID = flows.GetMeterIdFromFlow(flow)
Shrey Baid26912972020-04-16 21:02:31 +05302495 logger.Debugw("downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002496
2497 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302498
2499 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2500 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Shrey Baid26912972020-04-16 21:02:31 +05302501 logger.Debugw("no-pending-flows-found--going-ahead-with-flow-install",
2502 log.Fields{
2503 "intf-id": intfID,
2504 "onu-id": onuID,
2505 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302506 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302507 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05302508 pendingFlowDelComplete := make(chan bool)
2509 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
2510 select {
2511 case <-pendingFlowDelComplete:
Shrey Baid26912972020-04-16 21:02:31 +05302512 logger.Debugw("all-pending-flow-deletes-completed",
2513 log.Fields{
2514 "intf-id": intfID,
2515 "onu-id": onuID,
2516 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302517 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302518
2519 case <-time.After(10 * time.Second):
Shrey Baid26912972020-04-16 21:02:31 +05302520 return olterrors.NewErrTimeout("pending-flow-deletes",
2521 log.Fields{
2522 "intf-id": intfID,
2523 "onu-id": onuID,
2524 "uni-id": uniID}, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +05302525 }
2526 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002527 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002528}
2529
Esin Karamanccb714b2019-11-29 15:02:06 +00002530// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002531func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002532 classifierInfo[PacketTagType] = DoubleTag
Shrey Baid26912972020-04-16 21:02:31 +05302533 logger.Debugw("add-multicast-flow", log.Fields{
2534 "classifier-info": classifierInfo,
2535 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002536
Esin Karaman65409d82020-03-18 10:58:18 +00002537 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002538 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002539 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002540 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002541 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
2542 //otherwise, classification is based on ipv4_dst by default.
2543 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
2544 mcastFlowClassificationByEthDst := false
2545
2546 if mcastFlowClassificationByEthDst {
2547 //replace ipDst with ethDst
2548 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
2549 flows.IsMulticastIp(ipv4Dst.(uint32)) {
2550 // replace ipv4_dst classifier with eth_dst
2551 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
2552 delete(classifierInfo, Ipv4Dst)
2553 classifierInfo[EthDst] = multicastMac
Shrey Baid26912972020-04-16 21:02:31 +05302554 logger.Debugw("multicast-ip-to-mac-conversion-success",
2555 log.Fields{
2556 "ip:": ipv4Dst.(uint32),
2557 "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002558 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002559 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002560 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002561
David K. Bainbridge794735f2020-02-11 21:01:37 -08002562 onuID := NoneOnuID
2563 uniID := NoneUniID
2564 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00002565
David K. Bainbridge794735f2020-02-11 21:01:37 -08002566 flowStoreCookie := getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302567 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05302568 logger.Infow("multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002569 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002570 }
npujarec5762e2020-01-01 14:08:48 +05302571 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00002572 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302573 return olterrors.NewErrNotFound("multicast-flow-id",
2574 log.Fields{
2575 "interface-id": networkInterfaceID,
2576 "onu-id": onuID,
2577 "uni-id": uniID,
2578 "gem-port-id": gemPortID,
2579 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002580 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002581 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002582 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2583 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002584 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002585 }
2586 groupID := actionInfo[GroupID].(uint32)
2587 multicastFlow := openoltpb2.Flow{
2588 FlowId: flowID,
2589 FlowType: Multicast,
2590 NetworkIntfId: int32(networkInterfaceID),
2591 GroupId: groupID,
2592 Classifier: classifierProto,
2593 Priority: int32(flow.Priority),
2594 Cookie: flow.Cookie}
2595
David K. Bainbridge794735f2020-02-11 21:01:37 -08002596 if err = f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002597 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002598 }
Shrey Baid26912972020-04-16 21:02:31 +05302599 logger.Info("multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002600 //get cached group
2601 group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true)
2602 if err == nil {
2603 //calling groupAdd to set group members after multicast flow creation
Andrea Campanellac63bba92020-03-10 17:01:04 +01002604 if err = f.ModifyGroup(ctx, group); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002605 //cached group can be removed now
2606 f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002607 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002608 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002609 }
2610 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002611
2612 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2613 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2614 int32(onuID),
2615 int32(uniID),
2616 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002617 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002618 }
2619 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002620}
2621
Esin Karaman65409d82020-03-18 10:58:18 +00002622//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2623func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2624 if inPort, ok := classifierInfo[InPort]; ok {
2625 nniInterfaceID, err := IntfIDFromNniPortNum(inPort.(uint32))
2626 if err != nil {
2627 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2628 }
2629 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002630 }
Esin Karaman65409d82020-03-18 10:58:18 +00002631 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302632 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002633 if e == nil && len(nniPorts) > 0 {
2634 return nniPorts[0], nil
2635 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302636 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002637}
2638
2639// AddGroup add or update the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002640func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002641 logger.Infow("add-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002642 if group == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002643 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002644 }
2645
2646 groupToOlt := openoltpb2.Group{
2647 GroupId: group.Desc.GroupId,
2648 Command: openoltpb2.Group_SET_MEMBERS,
2649 Action: f.buildGroupAction(),
2650 }
2651
Shrey Baid26912972020-04-16 21:02:31 +05302652 logger.Debugw("sending-group-to-device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05302653 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002654 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002655 return olterrors.NewErrAdapter("add-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002656 }
2657 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05302658 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002659 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002660 }
Shrey Baid26912972020-04-16 21:02:31 +05302661 logger.Infow("add-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002662 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002663}
2664
2665//buildGroupAction creates and returns a group action
2666func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2667 var actionCmd openoltpb2.ActionCmd
2668 var action openoltpb2.Action
2669 action.Cmd = &actionCmd
2670 //pop outer vlan
2671 action.Cmd.RemoveOuterTag = true
2672 return &action
2673}
2674
2675// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002676func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002677 logger.Infow("modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002678 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002679 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002680 }
2681
Andrea Campanellac63bba92020-03-10 17:01:04 +01002682 newGroup := f.buildGroup(group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002683 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302684 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002685
2686 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002687 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002688 }
2689
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002690 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002691 if groupExists {
2692 // group already exists
2693 current = f.buildGroup(group.Desc.GroupId, val.Desc.GetBuckets())
Shrey Baid26912972020-04-16 21:02:31 +05302694 logger.Debugw("modify-group--group exists",
2695 log.Fields{
2696 "group on the device": val,
2697 "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002698 } else {
2699 current = f.buildGroup(group.Desc.GroupId, nil)
2700 }
2701
Shrey Baid26912972020-04-16 21:02:31 +05302702 logger.Debugw("modify-group--comparing-current-and-new",
2703 log.Fields{
2704 "group on the device": current,
2705 "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002706 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002707 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002708 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002709 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002710
Shrey Baid26912972020-04-16 21:02:31 +05302711 logger.Infow("modify-group--differences found", log.Fields{
2712 "membersToBeAdded": membersToBeAdded,
2713 "membersToBeRemoved": membersToBeRemoved,
2714 "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002715
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002716 groupToOlt := openoltpb2.Group{
2717 GroupId: group.Desc.GroupId,
2718 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002719 var errAdd, errRemoved error
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002720 if membersToBeAdded != nil && len(membersToBeAdded) > 0 {
2721 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2722 groupToOlt.Members = membersToBeAdded
2723 //execute addMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002724 errAdd = f.callGroupAddRemove(&groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002725 }
2726 if membersToBeRemoved != nil && len(membersToBeRemoved) > 0 {
2727 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2728 groupToOlt.Members = membersToBeRemoved
2729 //execute removeMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002730 errRemoved = f.callGroupAddRemove(&groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002731 }
2732
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002733 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002734 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302735 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002736 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002737 }
Shrey Baid26912972020-04-16 21:02:31 +05302738 logger.Infow("modify-group-was-success--storing-group",
2739 log.Fields{
2740 "group": group,
2741 "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002742 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302743 logger.Warnw("one-of-the-group-add/remove-operations-failed--cannot-save-group-modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002744 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002745 if errAdd != nil {
2746 return errAdd
2747 }
2748 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002749 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002750 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002751}
2752
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002753//callGroupAddRemove performs add/remove buckets operation for the indicated group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002754func (f *OpenOltFlowMgr) callGroupAddRemove(group *openoltpb2.Group) error {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002755 if err := f.performGroupOperation(group); err != nil {
2756 st, _ := status.FromError(err)
2757 //ignore already exists error code
2758 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002759 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002760 }
2761 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002762 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002763}
2764
2765//findDiff compares group members and finds members which only exists in groups2
2766func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2767 var members []*openoltpb2.GroupMember
2768 for _, bucket := range group2.Members {
2769 if !f.contains(group1.Members, bucket) {
2770 // bucket does not exist and must be added
2771 members = append(members, bucket)
2772 }
2773 }
2774 return members
2775}
2776
2777//contains returns true if the members list contains the given member; false otherwise
2778func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2779 for _, groupMember := range members {
2780 if groupMember.InterfaceId == member.InterfaceId {
2781 return true
2782 }
2783 }
2784 return false
2785}
2786
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002787//performGroupOperation call performGroupOperation operation of openolt proto
2788func (f *OpenOltFlowMgr) performGroupOperation(group *openoltpb2.Group) error {
Shrey Baid26912972020-04-16 21:02:31 +05302789 logger.Debugw("sending-group-to-device",
2790 log.Fields{
2791 "groupToOlt": group,
2792 "command": group.Command})
Esin Karamanccb714b2019-11-29 15:02:06 +00002793 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2794 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002795 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002796 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002797 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002798}
2799
2800//buildGroup build openoltpb2.Group from given group id and bucket list
2801func (f *OpenOltFlowMgr) buildGroup(groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
2802 group := openoltpb2.Group{
2803 GroupId: groupID}
2804 // create members of the group
2805 if buckets != nil {
2806 for _, ofBucket := range buckets {
2807 member := f.buildMember(ofBucket)
2808 if member != nil && !f.contains(group.Members, member) {
2809 group.Members = append(group.Members, member)
2810 }
2811 }
2812 }
2813 return &group
2814}
2815
2816//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
2817func (f *OpenOltFlowMgr) buildMember(ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
2818 var outPort uint32
2819 outPortFound := false
2820 for _, ofAction := range ofBucket.Actions {
2821 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2822 outPort = ofAction.GetOutput().Port
2823 outPortFound = true
2824 }
2825 }
2826
2827 if !outPortFound {
Shrey Baid26912972020-04-16 21:02:31 +05302828 logger.Debugw("bucket-skipped-since-no-out-port-found-in-it", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002829 return nil
2830 }
2831 interfaceID := IntfIDFromUniPortNum(outPort)
Shrey Baid26912972020-04-16 21:02:31 +05302832 logger.Debugw("got-associated-interface-id-of-the-port",
2833 log.Fields{
2834 "portNumber:": outPort,
2835 "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002836 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2837 member := openoltpb2.GroupMember{
2838 InterfaceId: interfaceID,
2839 InterfaceType: openoltpb2.GroupMember_PON,
2840 GemPortId: groupInfo.gemPortID,
2841 Priority: groupInfo.servicePriority,
2842 }
2843 //add member to the group
2844 return &member
2845 }
Shrey Baid26912972020-04-16 21:02:31 +05302846 logger.Warnf("bucket-skipped-since-interface-2-gem-mapping-cannot-be-found", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002847 return nil
2848}
2849
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002850//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04002851func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002852
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002853 onuDev, err := f.getOnuDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302854 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302855 logger.Errorw("couldnt-find-onu-child-device",
2856 log.Fields{
2857 "intf-id": intfID,
2858 "onu-id": onuID,
2859 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002860 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302861 }
Shrey Baid26912972020-04-16 21:02:31 +05302862 logger.Debugw("got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002863
Manikkaraj kb1d51442019-07-23 10:41:02 -04002864 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002865 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Matteo Scandolo92186242020-06-12 10:54:18 -07002866 logger.Debugw("sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
manikkaraj k17652a72019-05-06 09:06:36 -04002867 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2868 tpDownloadMsg,
2869 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302870 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002871 onuDev.deviceType,
2872 onuDev.deviceID,
2873 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002874 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302875 return olterrors.NewErrCommunication("send-techprofile-download-request",
2876 log.Fields{
2877 "from-adapter": f.deviceHandler.device.Type,
2878 "to-adapter": onuDev.deviceType,
2879 "onu-id": onuDev.deviceID,
2880 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002881 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002882 logger.Infow("success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302883 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302884}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002885
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302886//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002887func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302888
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002889 f.onuGemInfoLock[intfID].Lock()
2890 defer f.onuGemInfoLock[intfID].Unlock()
2891
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302892 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2893 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002894 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002895 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302896 }
Shrey Baid26912972020-04-16 21:02:31 +05302897 logger.Infow("updated-onuinfo",
2898 log.Fields{
2899 "intf-id": intfID,
2900 "onu-id": onuID,
2901 "serial-num": serialNum,
2902 "onu": onu,
2903 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002904 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002905}
2906
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302907//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302908func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002909
2910 f.onuGemInfoLock[intfID].Lock()
2911 defer f.onuGemInfoLock[intfID].Unlock()
2912
Shrey Baid26912972020-04-16 21:02:31 +05302913 logger.Infow("adding-gem-to-onu-info-map",
2914 log.Fields{
2915 "gem": gemPort,
2916 "intf": intfID,
2917 "onu": onuID,
2918 "device-id": f.deviceHandler.device.Id,
2919 "onu-gem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302920 onugem := f.onuGemInfo[intfID]
2921 // update the gem to the local cache as well as to kv strore
2922 for idx, onu := range onugem {
2923 if onu.OnuID == onuID {
2924 // check if gem already exists , else update the cache and kvstore
2925 for _, gem := range onu.GemPorts {
2926 if gem == gemPort {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002927 logger.Debugw("gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302928 log.Fields{
2929 "gem": gemPort,
2930 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302931 return
2932 }
2933 }
2934 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2935 f.onuGemInfo[intfID] = onugem
2936 }
2937 }
npujarec5762e2020-01-01 14:08:48 +05302938 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302939 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302940 logger.Errorw("failed-to-add-gem-to-onu",
2941 log.Fields{
2942 "intf-id": intfID,
2943 "onu-id": onuID,
2944 "gemPort": gemPort,
2945 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002946 return
2947 }
Shrey Baid26912972020-04-16 21:02:31 +05302948 logger.Infow("gem-added-to-onu-info-map",
2949 log.Fields{
2950 "gem": gemPort,
2951 "intf": intfID,
2952 "onu": onuID,
2953 "device-id": f.deviceHandler.device.Id,
2954 "onu-gem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002955}
2956
2957// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002958
2959//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 -07002960func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302961
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002962 f.onuGemInfoLock[intfID].Lock()
2963 defer f.onuGemInfoLock[intfID].Unlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302964
Shrey Baid26912972020-04-16 21:02:31 +05302965 logger.Infow("getting-onu-id-from-gem-port-and-pon-port",
2966 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002967 "device-id": f.deviceHandler.device.Id,
2968 "onu-geminfo": f.onuGemInfo[intfID],
2969 "intf-id": intfID,
2970 "gemport-id": gemPortID})
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002971
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302972 // get onuid from the onugem info cache
2973 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002974
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302975 for _, onu := range onugem {
2976 for _, gem := range onu.GemPorts {
2977 if gem == gemPortID {
2978 return onu.OnuID, nil
2979 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002980 }
2981 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302982 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002983 "interface-id": intfID,
2984 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00002985 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002986}
2987
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002988//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302989func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002990 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002991 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002992 var err error
2993
2994 if packetIn.IntfType == "pon" {
2995 // packet indication does not have serial number , so sending as nil
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002996 if onuID, err = f.getOnuIDfromGemPortMap(packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002997 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002998 return logicalPortNum, err
2999 }
3000 if packetIn.PortNo != 0 {
3001 logicalPortNum = packetIn.PortNo
3002 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003003 uniID := uint32(0) // FIXME - multi-uni support
3004 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003005 }
3006 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
npujarec5762e2020-01-01 14:08:48 +05303007 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003008 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003009 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003010 }
Shrey Baid26912972020-04-16 21:02:31 +05303011 logger.Infow("retrieved-logicalport-from-packet-in",
3012 log.Fields{
3013 "logical-port-num": logicalPortNum,
3014 "intf-type": packetIn.IntfType,
3015 "packet": hex.EncodeToString(packetIn.Pkt),
3016 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003017 return logicalPortNum, nil
3018}
3019
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003020//GetPacketOutGemPortID returns gemPortId
npujarec5762e2020-01-01 14:08:48 +05303021func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003022 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003023 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303024
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003025 f.onuGemInfoLock[intfID].Lock()
3026 defer f.onuGemInfoLock[intfID].Unlock()
3027
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303028 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
3029
3030 gemPortID, ok := f.packetInGemPort[pktInkey]
3031 if ok {
Shrey Baid26912972020-04-16 21:02:31 +05303032 logger.Debugw("found-gemport-for-pktin-key",
3033 log.Fields{
3034 "pktinkey": pktInkey,
3035 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303036 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003037 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303038 //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 +05303039 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303040 if err == nil {
3041 if gemPortID != 0 {
3042 f.packetInGemPort[pktInkey] = gemPortID
Shrey Baid26912972020-04-16 21:02:31 +05303043 logger.Infow("found-gem-port-from-kv-store-and-updating-cache-with-gemport",
3044 log.Fields{
3045 "pktinkey": pktInkey,
3046 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303047 return gemPortID, nil
3048 }
3049 }
Shrey Baid26912972020-04-16 21:02:31 +05303050 return uint32(0), olterrors.NewErrNotFound("gem-port",
3051 log.Fields{
3052 "pktinkey": pktInkey,
3053 "gem": gemPortID}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003054}
3055
npujarec5762e2020-01-01 14:08:48 +05303056func installFlowOnAllGemports(ctx context.Context,
3057 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003058 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003059 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05303060 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303061 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303062 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003063 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003064 args map[string]uint32,
3065 classifier map[string]interface{}, action map[string]interface{},
3066 logicalFlow *ofp.OfpFlowStats,
3067 gemPorts []uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303068 TpInst *tp.TechProfile,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003069 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00003070 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003071 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003072 vlanID ...uint32) {
Shrey Baid26912972020-04-16 21:02:31 +05303073 logger.Debugw("installing-flow-on-all-gem-ports",
3074 log.Fields{
3075 "FlowType": FlowType,
3076 "gemPorts": gemPorts,
3077 "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05303078
Gamze Abaka724d0852020-03-18 12:10:24 +00003079 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
3080 // We need to trim prefix "0b", before further processing
3081 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
3082 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
3083
3084 // If a particular character in the string is set to '1', identify the index of this character from
3085 // the LSB position which marks the PCP bit consumed by the given gem port.
3086 // This PCP bit now becomes a classifier in the flow.
3087
3088 attributes := TpInst.DownstreamGemPortAttributeList
3089 if direction == Upstream {
3090 attributes = TpInst.UpstreamGemPortAttributeList
3091 }
3092
3093 for _, gemPortAttribute := range attributes {
3094 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
3095 continue
3096 }
3097 gemPortID := gemPortAttribute.GemportID
3098 if allPbitsMarked(gemPortAttribute.PbitMap) {
3099 classifier[VlanPcp] = uint32(VlanPCPMask)
3100 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003101 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003102 } else if FlowType == EapolFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003103 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 +00003104 }
3105 } else {
3106 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
3107 if pbitSet == BinaryBit1 {
3108 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3109 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003110 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003111 } else if FlowType == EapolFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003112 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 +00003113 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05303114 }
3115 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04003116 }
3117 }
3118}
3119
Gamze Abaka724d0852020-03-18 12:10:24 +00003120func allPbitsMarked(pbitMap string) bool {
3121 for pos, pBit := range pbitMap {
3122 if pos >= 2 && pBit != BinaryBit1 {
3123 return false
3124 }
3125 }
3126 return true
3127}
3128
David K. Bainbridge794735f2020-02-11 21:01:37 -08003129func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05303130 logger.Debug("adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003131 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003132 classifier[PacketTagType] = DoubleTag
3133 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003134 /* We manage flowId resource pool on per PON port basis.
3135 Since this situation is tricky, as a hack, we pass the NNI port
3136 index (network_intf_id) as PON port Index for the flowId resource
3137 pool. Also, there is no ONU Id available for trapping DHCP packets
3138 on NNI port, use onu_id as -1 (invalid)
3139 ****************** CAVEAT *******************
3140 This logic works if the NNI Port Id falls within the same valid
3141 range of PON Port Ids. If this doesn't work for some OLT Vendor
3142 we need to have a re-look at this.
3143 *********************************************
3144 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003145 onuID := -1
3146 uniID := -1
3147 gemPortID := -1
3148 allocID := -1
David K. Bainbridge794735f2020-02-11 21:01:37 -08003149 networkInterfaceID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303150 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303151 return olterrors.NewErrNotFound("nni-intreface-id",
3152 log.Fields{
3153 "classifier": classifier,
3154 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003155 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303156 }
3157
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003158 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303159 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05303160 logger.Info("flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003161 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003162 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003163 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003164 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303165 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id",
3166 log.Fields{
3167 "interface-id": networkInterfaceID,
3168 "onu-id": onuID,
3169 "uni-id": uniID,
3170 "gem-port-id": gemPortID,
3171 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003172 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003173 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003174 classifierProto, err := makeOpenOltClassifierField(classifier)
3175 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003176 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003177 }
Shrey Baid26912972020-04-16 21:02:31 +05303178 logger.Debugw("created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003179 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003180 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003181 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003182 }
Shrey Baid26912972020-04-16 21:02:31 +05303183 logger.Debugw("created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003184 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3185 OnuId: int32(onuID), // OnuId not required
3186 UniId: int32(uniID), // UniId not used
3187 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07003188 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003189 AllocId: int32(allocID), // AllocId not used
3190 NetworkIntfId: int32(networkInterfaceID),
3191 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003192 Classifier: classifierProto,
3193 Action: actionProto,
3194 Priority: int32(logicalFlow.Priority),
3195 Cookie: logicalFlow.Cookie,
3196 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003197 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003198 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003199 }
Shrey Baid26912972020-04-16 21:02:31 +05303200 logger.Info("dhcp-trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003201 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3202 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3203 int32(onuID),
3204 int32(uniID),
3205 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003206 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003207 }
3208 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003209}
salmansiddiqui7ac62132019-08-22 03:58:50 +00003210
Esin Karamanae41e2b2019-12-17 18:13:13 +00003211//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
3212func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
3213 var packetType string
3214 ovid, ivid := false, false
3215 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
3216 vid := vlanID & VlanvIDMask
3217 if vid != ReservedVlan {
3218 ovid = true
3219 }
3220 }
3221 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
3222 vid := uint32(metadata)
3223 if vid != ReservedVlan {
3224 ivid = true
3225 }
3226 }
3227 if ovid && ivid {
3228 packetType = DoubleTag
3229 } else if !ovid && !ivid {
3230 packetType = Untagged
3231 } else {
3232 packetType = SingleTag
3233 }
3234 return packetType
3235}
3236
3237//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08003238func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05303239 logger.Infow("adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003240 action := make(map[string]interface{})
3241 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
3242 action[TrapToHost] = true
3243 /* We manage flowId resource pool on per PON port basis.
3244 Since this situation is tricky, as a hack, we pass the NNI port
3245 index (network_intf_id) as PON port Index for the flowId resource
3246 pool. Also, there is no ONU Id available for trapping packets
3247 on NNI port, use onu_id as -1 (invalid)
3248 ****************** CAVEAT *******************
3249 This logic works if the NNI Port Id falls within the same valid
3250 range of PON Port Ids. If this doesn't work for some OLT Vendor
3251 we need to have a re-look at this.
3252 *********************************************
3253 */
3254 onuID := -1
3255 uniID := -1
3256 gemPortID := -1
3257 allocID := -1
3258 networkInterfaceID, err := getNniIntfID(classifier, action)
3259 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303260 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003261 "classifier": classifier,
3262 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003263 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003264 }
3265 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303266 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05303267 logger.Info("igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003268 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003269 }
npujarec5762e2020-01-01 14:08:48 +05303270 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003271 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303272 return olterrors.NewErrNotFound("igmp-flow-id",
3273 log.Fields{
3274 "interface-id": networkInterfaceID,
3275 "onu-id": onuID,
3276 "uni-id": uniID,
3277 "gem-port-id": gemPortID,
3278 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003279 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003280 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003281 classifierProto, err := makeOpenOltClassifierField(classifier)
3282 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003283 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003284 }
Shrey Baid26912972020-04-16 21:02:31 +05303285 logger.Debugw("created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003286 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003287 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003288 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003289 }
Shrey Baid26912972020-04-16 21:02:31 +05303290 logger.Debugw("created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003291 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3292 OnuId: int32(onuID), // OnuId not required
3293 UniId: int32(uniID), // UniId not used
3294 FlowId: flowID,
3295 FlowType: Downstream,
3296 AllocId: int32(allocID), // AllocId not used
3297 NetworkIntfId: int32(networkInterfaceID),
3298 GemportId: int32(gemPortID), // GemportId not used
3299 Classifier: classifierProto,
3300 Action: actionProto,
3301 Priority: int32(logicalFlow.Priority),
3302 Cookie: logicalFlow.Cookie,
3303 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003304 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003305 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003306 }
Shrey Baid26912972020-04-16 21:02:31 +05303307 logger.Info("igmp-trap-on-nni-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003308 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3309 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3310 int32(onuID),
3311 int32(uniID),
3312 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003313 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003314 }
3315 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003316}
3317
salmansiddiqui7ac62132019-08-22 03:58:50 +00003318func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
3319 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05303320 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003321 }
3322 if Dir == tp_pb.Direction_UPSTREAM {
3323 return "upstream", nil
3324 } else if Dir == tp_pb.Direction_DOWNSTREAM {
3325 return "downstream", nil
3326 }
3327 return "", nil
3328}
3329
npujarec5762e2020-01-01 14:08:48 +05303330func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00003331 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003332 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00003333 var gemPort uint32
3334 intfID := args[IntfID]
3335 onuID := args[OnuID]
3336 uniID := args[UniID]
3337 portNo := args[PortNo]
3338 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00003339 if ipProto, ok := classifierInfo[IPProto]; ok {
3340 if ipProto.(uint32) == IPProtoDhcp {
Matteo Scandolo92186242020-06-12 10:54:18 -07003341 logger.Infow("adding-dhcp-flow", log.Fields{
3342 "tp-id": tpID,
3343 "alloc-id": allocID,
3344 "intf-id": intfID,
3345 "onu-id": onuID,
3346 "uni-id": uniID,
3347 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003348 if pcp, ok := classifierInfo[VlanPcp]; ok {
3349 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3350 tp_pb.Direction_UPSTREAM,
3351 pcp.(uint32))
3352 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00003353
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003354 f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003355 } else {
3356 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003357 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003358 }
3359
Girish Gowdra32625212020-04-29 11:26:35 -07003360 } else if ipProto.(uint32) == IgmpProto {
Shrey Baid26912972020-04-16 21:02:31 +05303361 logger.Infow("adding-us-igmp-flow",
3362 log.Fields{
3363 "intf-id": intfID,
3364 "onu-id": onuID,
3365 "uni-id": uniID,
3366 "classifier-info:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003367 if pcp, ok := classifierInfo[VlanPcp]; ok {
3368 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3369 tp_pb.Direction_UPSTREAM,
3370 pcp.(uint32))
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003371 f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003372 } else {
3373 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003374 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003375 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003376 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303377 logger.Errorw("invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003378 return
3379 }
3380 } else if ethType, ok := classifierInfo[EthType]; ok {
3381 if ethType.(uint32) == EapEthType {
Matteo Scandolo92186242020-06-12 10:54:18 -07003382 logger.Infow("adding-eapol-flow", log.Fields{
3383 "intf-id": intfID,
3384 "onu-id": onuID,
3385 "uni-id": uniID,
3386 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003387 var vlanID uint32
3388 if val, ok := classifierInfo[VlanVid]; ok {
3389 vlanID = (val.(uint32)) & VlanvIDMask
3390 } else {
3391 vlanID = DefaultMgmtVlan
3392 }
3393 if pcp, ok := classifierInfo[VlanPcp]; ok {
3394 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3395 tp_pb.Direction_UPSTREAM,
3396 pcp.(uint32))
3397
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003398 f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003399 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003400 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003401 }
3402 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003403 } else if _, ok := actionInfo[PushVlan]; ok {
Matteo Scandolo92186242020-06-12 10:54:18 -07003404 logger.Infow("adding-upstream-data-rule", log.Fields{
3405 "intf-id": intfID,
3406 "onu-id": onuID,
3407 "uni-id": uniID,
3408 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003409 if pcp, ok := classifierInfo[VlanPcp]; ok {
3410 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3411 tp_pb.Direction_UPSTREAM,
3412 pcp.(uint32))
3413 //Adding HSIA upstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003414 f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003415 } else {
3416 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003417 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003418 }
3419 } else if _, ok := actionInfo[PopVlan]; ok {
Matteo Scandolo92186242020-06-12 10:54:18 -07003420 logger.Infow("adding-downstream-data-rule", log.Fields{
3421 "intf-id": intfID,
3422 "onu-id": onuID,
3423 "uni-id": uniID,
3424 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003425 if pcp, ok := classifierInfo[VlanPcp]; ok {
3426 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05003427 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003428 pcp.(uint32))
3429 //Adding HSIA downstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003430 f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003431 } else {
3432 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003433 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003434 }
3435 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303436 logger.Errorw("invalid-flow-type-to-handle",
3437 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003438 "intf-id": intfID,
3439 "onu-id": onuID,
3440 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05303441 "classifier": classifierInfo,
3442 "action": actionInfo,
3443 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003444 return
3445 }
3446 // Send Techprofile download event to child device in go routine as it takes time
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003447 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003448}
3449
Gamze Abakafee36392019-10-03 11:17:24 +00003450func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
3451 flowIDList := f.flowsUsedByGemPort[gemPK]
3452 if len(flowIDList) > 1 {
3453 return true
3454 }
3455 return false
3456}
3457
npujarec5762e2020-01-01 14:08:48 +05303458func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3459 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003460 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3461 for _, currentGemPort := range currentGemPorts {
3462 for _, tpGemPort := range tpGemPorts {
3463 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3464 return true, currentGemPort
3465 }
3466 }
3467 }
Girish Gowdra54934262019-11-13 14:19:55 +05303468 if tpInst.InstanceCtrl.Onu == "single-instance" {
3469 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
npujarec5762e2020-01-01 14:08:48 +05303470 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID)
3471 f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID)
Girish Gowdra54934262019-11-13 14:19:55 +05303472
3473 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3474 // still be used on other uni ports.
3475 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3476 // on any other uni port.
npujarec5762e2020-01-01 14:08:48 +05303477 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID)
Shrey Baid26912972020-04-16 21:02:31 +05303478 logger.Debugw("got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303479 for i := 0; i < len(tpInstances); i++ {
3480 tpI := tpInstances[i]
3481 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303482 for _, tpGemPort := range tpGemPorts {
3483 if tpGemPort.GemportID != gemPortID {
Shrey Baid26912972020-04-16 21:02:31 +05303484 logger.Debugw("single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303485 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303486 }
3487 }
3488 }
3489 }
Shrey Baid26912972020-04-16 21:02:31 +05303490 logger.Debug("tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003491 return false, 0
3492}
3493
salmansiddiqui7ac62132019-08-22 03:58:50 +00003494func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003495 for _, field := range flows.GetOfbFields(flow) {
3496 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003497 classifierInfo[EthType] = field.GetEthType()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003498 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003499 } else if field.Type == flows.ETH_DST {
3500 classifierInfo[EthDst] = field.GetEthDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003501 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003502 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003503 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003504 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003505 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003506 classifierInfo[InPort] = field.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003507 logger.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003508 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303509 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00003510 logger.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003511 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003512 classifierInfo[VlanPcp] = field.GetVlanPcp()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003513 logger.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003514 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003515 classifierInfo[UDPDst] = field.GetUdpDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003516 logger.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003517 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003518 classifierInfo[UDPSrc] = field.GetUdpSrc()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003519 logger.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003520 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003521 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003522 logger.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003523 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003524 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003525 logger.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003526 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003527 classifierInfo[Metadata] = field.GetTableMetadata()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003528 logger.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003529 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003530 classifierInfo[TunnelID] = field.GetTunnelId()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003531 logger.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003532 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303533 logger.Errorw("un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003534 return
3535 }
3536 }
3537}
3538
3539func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003540 for _, action := range flows.GetActions(flow) {
3541 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003542 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003543 actionInfo[Output] = out.GetPort()
Shrey Baid26912972020-04-16 21:02:31 +05303544 logger.Debugw("action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003545 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003546 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003547 }
Scott Baker355d1742019-10-24 10:57:52 -07003548 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003549 actionInfo[PopVlan] = true
Girish Kumar2ad402b2020-03-20 19:45:12 +00003550 logger.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003551 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003552 if out := action.GetPush(); out != nil {
3553 if tpid := out.GetEthertype(); tpid != 0x8100 {
Shrey Baid26912972020-04-16 21:02:31 +05303554 logger.Errorw("invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003555 } else {
3556 actionInfo[PushVlan] = true
3557 actionInfo[TPID] = tpid
Girish Kumar2ad402b2020-03-20 19:45:12 +00003558 logger.Debugw("action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303559 log.Fields{
3560 "push-tpid": actionInfo[TPID].(uint32),
3561 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003562 }
3563 }
Scott Baker355d1742019-10-24 10:57:52 -07003564 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003565 if out := action.GetSetField(); out != nil {
3566 if field := out.GetField(); field != nil {
3567 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003568 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003569 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00003570 /*logger.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
Esin Karamanccb714b2019-11-29 15:02:06 +00003571 formulateSetFieldActionInfoFromFlow(field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003572 }
3573 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003574 } else if action.Type == flows.GROUP {
3575 formulateGroupActionInfoFromFlow(action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003576 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003577 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003578 }
3579 }
3580 return nil
3581}
3582
Esin Karamanccb714b2019-11-29 15:02:06 +00003583func formulateSetFieldActionInfoFromFlow(field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
3584 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003585 fieldtype := ofbField.GetType()
3586 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003587 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3588 actionInfo[VlanVid] = vlan & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00003589 logger.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003590 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303591 logger.Error("no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003592 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003593 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3594 pcp := ofbField.GetVlanPcp()
3595 actionInfo[VlanPcp] = pcp
3596 log.Debugw("action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003597 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003598 logger.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003599 }
3600 }
3601}
3602
3603func formulateGroupActionInfoFromFlow(action *ofp.OfpAction, actionInfo map[string]interface{}) {
3604 if action.GetGroup() == nil {
Shrey Baid26912972020-04-16 21:02:31 +05303605 logger.Warn("no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003606 } else {
3607 actionInfo[GroupID] = action.GetGroup().GroupId
Girish Kumar2ad402b2020-03-20 19:45:12 +00003608 logger.Debugw("action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003609 }
3610}
3611
salmansiddiqui7ac62132019-08-22 03:58:50 +00003612func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003613 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Shrey Baid26912972020-04-16 21:02:31 +05303614 logger.Debug("controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003615 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3616 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003617 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003618 classifierInfo[InPort] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303619 logger.Debugw("upstream-pon-to-controller-flow--inport-in-tunnelid",
3620 log.Fields{
3621 "newinport": classifierInfo[InPort].(uint32),
3622 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003623 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303624 return olterrors.NewErrNotFound("child-in-port",
3625 log.Fields{
3626 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3627 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003628 }
3629 }
3630 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303631 logger.Debug("non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003632 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003633 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003634 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003635 actionInfo[Output] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303636 logger.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid",
3637 log.Fields{
3638 "newoutport": actionInfo[Output].(uint32),
3639 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003640 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303641 return olterrors.NewErrNotFound("out-port",
3642 log.Fields{
3643 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3644 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003645 }
3646 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3647 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003648 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003649 classifierInfo[InPort] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303650 logger.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid",
3651 log.Fields{
3652 "newinport": actionInfo[Output].(uint32),
3653 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003654 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303655 return olterrors.NewErrNotFound("nni-port",
3656 log.Fields{
3657 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3658 "in-port": classifierInfo[InPort].(uint32),
3659 "out-port": actionInfo[Output].(uint32),
3660 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003661 }
3662 }
3663 }
3664 return nil
3665}
Gamze Abakafee36392019-10-03 11:17:24 +00003666
Chaitrashree G S90a17952019-11-14 21:51:21 -05003667func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003668 /* Metadata 8 bytes:
3669 Most Significant 2 Bytes = Inner VLAN
3670 Next 2 Bytes = Tech Profile ID(TPID)
3671 Least Significant 4 Bytes = Port ID
3672 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3673 subscriber related flows.
3674 */
3675 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
3676 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003677 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003678 }
3679 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003680 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003681}
3682
3683func appendUnique(slice []uint32, item uint32) []uint32 {
3684 for _, sliceElement := range slice {
3685 if sliceElement == item {
3686 return slice
3687 }
3688 }
3689 return append(slice, item)
3690}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303691
3692// getNniIntfID gets nni intf id from the flow classifier/action
3693func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
3694
3695 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3696 if portType == voltha.Port_PON_OLT {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003697 intfID, err := IntfIDFromNniPortNum(action[Output].(uint32))
3698 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003699 logger.Debugw("invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003700 log.Fields{
3701 "port-number": action[Output].(uint32),
3702 "error": err})
3703 return uint32(0), err
3704 }
Shrey Baid26912972020-04-16 21:02:31 +05303705 logger.Infow("output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303706 return intfID, nil
3707 } else if portType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003708 intfID, err := IntfIDFromNniPortNum(classifier[InPort].(uint32))
3709 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003710 logger.Debugw("invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003711 log.Fields{
3712 "port-number": action[Output].(uint32),
3713 "error": err})
3714 return uint32(0), err
3715 }
Shrey Baid26912972020-04-16 21:02:31 +05303716 logger.Infow("input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303717 return intfID, nil
3718 }
3719 return uint32(0), nil
3720}
3721
3722// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
npujarec5762e2020-01-01 14:08:48 +05303723func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303724 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
3725
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003726 f.onuGemInfoLock[intfID].Lock()
3727 defer f.onuGemInfoLock[intfID].Unlock()
3728
Matt Jeanneret1719a072019-12-20 14:50:14 -05003729 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303730 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003731 if lookupGemPort == gemPort {
Shrey Baid26912972020-04-16 21:02:31 +05303732 logger.Infow("pktin-key/value-found-in-cache--no-need-to-update-kv--assume-both-in-sync",
3733 log.Fields{
3734 "pktinkey": pktInkey,
3735 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003736 return
3737 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303738 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003739 f.packetInGemPort[pktInkey] = gemPort
3740
npujarec5762e2020-01-01 14:08:48 +05303741 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Shrey Baid26912972020-04-16 21:02:31 +05303742 logger.Infow("pktin-key-not-found-in-local-cache-value-is-different--updating-cache-and-kv-store",
3743 log.Fields{
3744 "pktinkey": pktInkey,
3745 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303746 return
3747}
3748
3749// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303750func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003751
3752 f.onuGemInfoLock[intfID].Lock()
3753 defer f.onuGemInfoLock[intfID].Unlock()
3754
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303755 onugem := f.onuGemInfo[intfID]
3756 for idx, onu := range onugem {
3757 if onu.OnuID == onuID {
3758 for _, uni := range onu.UniPorts {
3759 if uni == portNum {
Shrey Baid26912972020-04-16 21:02:31 +05303760 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 +05303761 return
3762 }
3763 }
3764 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3765 f.onuGemInfo[intfID] = onugem
3766 }
3767 }
npujarec5762e2020-01-01 14:08:48 +05303768 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303769}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303770
npujarec5762e2020-01-01 14:08:48 +05303771func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3772 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303773 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303774 logger.Error("failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303775 return
3776 }
3777 for gem, FlowIDs := range flowIDsList {
3778 gemPK := gemPortKey{intf, uint32(gem)}
3779 f.flowsUsedByGemPort[gemPK] = FlowIDs
3780 }
3781 return
3782}
Esin Karamanccb714b2019-11-29 15:02:06 +00003783
3784//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
3785//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05303786func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
3787 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00003788 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303789 logger.Error("failed-to-get-pon-interface-to-multicast-queue-map")
Esin Karamanccb714b2019-11-29 15:02:06 +00003790 return
3791 }
3792 for intf, queueInfo := range storedMulticastQueueMap {
3793 q := queueInfoBrief{
3794 gemPortID: queueInfo[0],
3795 servicePriority: queueInfo[1],
3796 }
3797 f.interfaceToMcastQueueMap[intf] = &q
3798 }
3799}
3800
3801//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
3802//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
3803//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05303804func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
3805 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00003806 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003807 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00003808 }
3809 if exists {
3810 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
3811 }
3812 return nil, exists, nil
3813}
3814
3815func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
3816 groupDesc := ofp.OfpGroupDesc{
3817 Type: ofp.OfpGroupType_OFPGT_ALL,
3818 GroupId: groupID,
3819 }
3820 groupEntry := ofp.OfpGroupEntry{
3821 Desc: &groupDesc,
3822 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003823 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003824 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00003825 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003826 bucket := ofp.OfpBucket{
3827 Actions: acts,
3828 }
3829 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00003830 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003831 return &groupEntry
3832}