blob: b489c0ac005d3cd8a0fbbd4e6a43db8228a96464 [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{
367 "intf-id": intfID,
368 "onu-id": onuID,
369 "uni-id": uniID,
370 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400371 return
372 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530373}
374
salmansiddiqui7ac62132019-08-22 03:58:50 +0000375// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530376func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400377
Shrey Baid26912972020-04-16 21:02:31 +0530378 logger.Debugw("CreateSchedulerQueues",
379 log.Fields{"dir": sq.direction,
380 "intf-id": sq.intfID,
381 "onu-id": sq.onuID,
382 "uni-id": sq.uniID,
383 "tp-id": sq.tpID,
384 "meter-id": sq.meterID,
385 "tp-inst": sq.tpInst,
386 "flowmetadata": sq.flowMetadata,
387 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400388
Gamze Abakafee36392019-10-03 11:17:24 +0000389 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000390 if err != nil {
391 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400392 }
393
394 /* Lets make a simple assumption that if the meter-id is present on the KV store,
395 * then the scheduler and queues configuration is applied on the OLT device
396 * in the given direction.
397 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000398
Manikkaraj kb1d51442019-07-23 10:41:02 -0400399 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530400 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530402 return olterrors.NewErrNotFound("meter",
403 log.Fields{"intf-id": sq.intfID,
404 "onu-id": sq.onuID,
405 "uni-id": sq.uniID,
406 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400407 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000408
Manikkaraj kb1d51442019-07-23 10:41:02 -0400409 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000410 if KvStoreMeter.MeterId == sq.meterID {
Shrey Baid26912972020-04-16 21:02:31 +0530411 logger.Debugw("scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400412 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400413 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530414 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800415 "unsupported": "meter-id",
416 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530417 "meter-id-in-flow": sq.meterID,
418 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400419 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000420
Shrey Baid26912972020-04-16 21:02:31 +0530421 logger.Debugw("meter-does-not-exist-creating-new",
422 log.Fields{
423 "meter-id": sq.meterID,
424 "direction": Direction,
425 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000426
Gamze Abakafee36392019-10-03 11:17:24 +0000427 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000428 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Gamze Abakafee36392019-10-03 11:17:24 +0000429 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000430 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400431 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000432
433 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530434 return olterrors.NewErrNotFound("scheduler-config",
435 log.Fields{
436 "intf-id": sq.intfID,
437 "direction": sq.direction,
438 "tp-inst": sq.tpInst,
439 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000440 }
441
Manikkaraj kb1d51442019-07-23 10:41:02 -0400442 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000443 if sq.flowMetadata != nil {
444 for _, meter := range sq.flowMetadata.Meters {
445 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400446 meterConfig = meter
Shrey Baid26912972020-04-16 21:02:31 +0530447 logger.Debugw("found-meter-config-from-flowmetadata",
448 log.Fields{"meterConfig": meterConfig,
449 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400450 break
451 }
452 }
453 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530454 logger.Errorw("flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400455 }
456 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530457 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800458 "reason": "Could-not-get-meterbands-from-flowMetadata",
459 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530460 "meter-id": sq.meterID,
461 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400462 } else if len(meterConfig.Bands) < MaxMeterBand {
Shrey Baid26912972020-04-16 21:02:31 +0530463 logger.Errorw("invalid-number-of-bands-in-meter",
464 log.Fields{"Bands": meterConfig.Bands,
465 "meter-id": sq.meterID,
466 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530467 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800468 "reason": "Invalid-number-of-bands-in-meter",
469 "meterband-count": len(meterConfig.Bands),
470 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530471 "meter-id": sq.meterID,
472 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400473 }
474 cir := meterConfig.Bands[0].Rate
475 cbs := meterConfig.Bands[0].BurstSize
476 eir := meterConfig.Bands[1].Rate
477 ebs := meterConfig.Bands[1].BurstSize
478 pir := cir + eir
479 pbs := cbs + ebs
480 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
481
Gamze Abakafee36392019-10-03 11:17:24 +0000482 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000483 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400484
npujarec5762e2020-01-01 14:08:48 +0530485 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530486 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
487 log.Fields{"intf-id": sq.intfID,
488 "direction": sq.direction,
489 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400490 }
491
salmansiddiqui7ac62132019-08-22 03:58:50 +0000492 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400493 * store the meter id on the KV store, for further reference.
494 */
npujarec5762e2020-01-01 14:08:48 +0530495 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 +0530496 return olterrors.NewErrAdapter("failed-updating-meter-id",
497 log.Fields{"onu-id": sq.onuID,
498 "meter-id": sq.meterID,
499 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400500 }
Shrey Baid26912972020-04-16 21:02:31 +0530501 logger.Infow("updated-meter-info-into-kv-store-successfully",
502 log.Fields{"direction": Direction,
503 "Meter": meterConfig,
504 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400505 return nil
506}
507
npujarec5762e2020-01-01 14:08:48 +0530508func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000509
510 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
511
512 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530513 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
514 log.Fields{"intf-id": sq.intfID,
515 "direction": sq.direction,
516 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000517 }
518
Shrey Baid26912972020-04-16 21:02:31 +0530519 logger.Debugw("sending-traffic-scheduler-create-to-device",
520 log.Fields{
521 "direction": sq.direction,
522 "TrafficScheds": TrafficSched,
523 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530524 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000525 IntfId: sq.intfID, OnuId: sq.onuID,
526 UniId: sq.uniID, PortNo: sq.uniPort,
527 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000528 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000529 }
Shrey Baid26912972020-04-16 21:02:31 +0530530 logger.Infow("successfully-created-traffic-schedulers", log.Fields{
531 "direction": sq.direction,
532 "traffic-queues": trafficQueues,
533 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000534
535 // On receiving the CreateTrafficQueues request, the driver should create corresponding
536 // downstream queues.
Shrey Baid26912972020-04-16 21:02:31 +0530537 logger.Debugw("sending-traffic-queues-create-to-device",
538 log.Fields{"direction": sq.direction,
539 "traffic-queues": trafficQueues,
540 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530541 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000542 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
543 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000544 TrafficQueues: trafficQueues,
545 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530546 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000547 }
Shrey Baid26912972020-04-16 21:02:31 +0530548 logger.Infow("successfully-created-traffic-schedulers", log.Fields{
549 "direction": sq.direction,
550 "traffic-queues": trafficQueues,
551 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000552
Esin Karamanccb714b2019-11-29 15:02:06 +0000553 if sq.direction == tp_pb.Direction_DOWNSTREAM {
554 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(sq.tpInst)
555 if len(multicastTrafficQueues) > 0 {
556 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
557 //assumed that there is only one queue per PON for the multicast service
558 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
559 //just put it in interfaceToMcastQueueMap to use for building group members
Shrey Baid26912972020-04-16 21:02:31 +0530560 logger.Debugw("multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000561 multicastQueuePerPonPort := multicastTrafficQueues[0]
562 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
563 gemPortID: multicastQueuePerPonPort.GemportId,
564 servicePriority: multicastQueuePerPonPort.Priority,
565 }
566 //also store the queue info in kv store
npujarec5762e2020-01-01 14:08:48 +0530567 f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID,
Esin Karamanccb714b2019-11-29 15:02:06 +0000568 multicastQueuePerPonPort.GemportId,
569 multicastQueuePerPonPort.Priority)
Shrey Baid26912972020-04-16 21:02:31 +0530570
571 logger.Infow("multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000572 }
573 }
574 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000575 return nil
576}
577
salmansiddiqui7ac62132019-08-22 03:58:50 +0000578// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530579func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400580
581 var Direction string
582 var SchedCfg *tp_pb.SchedulerConfig
583 var err error
Shrey Baid26912972020-04-16 21:02:31 +0530584 logger.Infow("removing-schedulers-and-queues-in-olt",
585 log.Fields{
586 "direction": sq.direction,
587 "intf-id": sq.intfID,
588 "onu-id": sq.onuID,
589 "uni-id": sq.uniID,
590 "uni-port": sq.uniPort,
591 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000592 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000593 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400594 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000595 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000596 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400597 Direction = "downstream"
598 }
599
Girish Kumar8f73fe02019-12-09 13:19:37 +0000600 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530601 return olterrors.NewErrNotFound("scheduler-config",
602 log.Fields{
603 "int-id": sq.intfID,
604 "direction": sq.direction,
605 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000606 }
607
npujarec5762e2020-01-01 14:08:48 +0530608 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400609 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530610 return olterrors.NewErrNotFound("meter",
611 log.Fields{
612 "onu-id": sq.onuID,
613 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400614 }
615 if KVStoreMeter == nil {
Shrey Baid26912972020-04-16 21:02:31 +0530616 logger.Warnw("no-meter-installed-yet",
617 log.Fields{
618 "direction": Direction,
619 "intf-id": sq.intfID,
620 "onu-id": sq.onuID,
621 "uni-id": sq.uniID,
622 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400623 return nil
624 }
625 cir := KVStoreMeter.Bands[0].Rate
626 cbs := KVStoreMeter.Bands[0].BurstSize
627 eir := KVStoreMeter.Bands[1].Rate
628 ebs := KVStoreMeter.Bands[1].BurstSize
629 pir := cir + eir
630 pbs := cbs + ebs
631
632 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
633
Gamze Abakafee36392019-10-03 11:17:24 +0000634 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000635 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000636
637 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
638 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530639 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
640 log.Fields{
641 "intf-id": sq.intfID,
642 "direction": sq.direction,
643 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000644 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400645
npujarec5762e2020-01-01 14:08:48 +0530646 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000647 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
648 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000649 TrafficQueues: TrafficQueues,
650 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000651 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530652 log.Fields{
653 "intf-id": sq.intfID,
654 "traffic-queues": TrafficQueues,
655 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400656 }
Shrey Baid26912972020-04-16 21:02:31 +0530657 logger.Infow("removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530658 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000659 IntfId: sq.intfID, OnuId: sq.onuID,
660 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400661 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000662 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530663 log.Fields{
664 "intf-id": sq.intfID,
665 "traffic-schedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400666 }
667
Shrey Baid26912972020-04-16 21:02:31 +0530668 logger.Infow("removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000669
670 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400671 * delete the meter id on the KV store.
672 */
npujarec5762e2020-01-01 14:08:48 +0530673 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400674 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530675 return olterrors.NewErrAdapter("unable-to-remove-meter",
676 log.Fields{
677 "onu": sq.onuID,
678 "meter": KVStoreMeter.MeterId,
679 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400680 }
Shrey Baid26912972020-04-16 21:02:31 +0530681 logger.Infow("removed-meter-from-KV-store-successfully",
682 log.Fields{
683 "meter-id": KVStoreMeter.MeterId,
684 "dir": Direction,
685 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400686 return err
687}
688
Gamze Abakafee36392019-10-03 11:17:24 +0000689// This function allocates tconts and GEM ports for an ONU
npujarec5762e2020-01-01 14:08:48 +0530690func (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 +0000691 var allocIDs []uint32
692 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530693 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530694 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000695 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000696
npujarec5762e2020-01-01 14:08:48 +0530697 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
698 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400699
700 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530701
Shrey Baid26912972020-04-16 21:02:31 +0530702 logger.Debugw("creating-new-tcont-and-gem", log.Fields{
703 "intf-id": intfID,
704 "onu-id": onuID,
705 "uni-id": uniID,
706 "device-id": f.deviceHandler.device.Id,
707 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530708
Manikkaraj kb1d51442019-07-23 10:41:02 -0400709 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530710 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000711 if techProfileInstance == nil {
Shrey Baid26912972020-04-16 21:02:31 +0530712 logger.Infow("tp-instance-not-found--creating-new",
713 log.Fields{
714 "path": tpPath,
715 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530716 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000717 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530718 // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +0530719 logger.Errorw("tp-instance-create-failed",
720 log.Fields{
721 "error": err,
722 "tp-id": TpID,
723 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000724 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530725 }
npujarec5762e2020-01-01 14:08:48 +0530726 f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530727 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530728 logger.Debugw("tech-profile-instance-already-exist-for-given port-name",
729 log.Fields{
730 "uni": uni,
731 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530732 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530733 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400734 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000735 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
736 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530737 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530738 logger.Errorw("CreateSchedulerQueues-failed-upstream",
739 log.Fields{
740 "error": err,
741 "meter-id": UsMeterID,
742 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000743 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400744 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530745 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400746 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000747 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
748 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530749 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530750 logger.Errorw("CreateSchedulerQueues-failed-downstream",
751 log.Fields{
752 "error": err,
753 "meter-id": DsMeterID,
754 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000755 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400756 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530757 }
Gamze Abakafee36392019-10-03 11:17:24 +0000758
759 allocID := techProfileInstance.UsScheduler.AllocID
Gamze Abakafee36392019-10-03 11:17:24 +0000760 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Gamze Abakafee36392019-10-03 11:17:24 +0000761 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400762 }
Gamze Abakafee36392019-10-03 11:17:24 +0000763
Girish Gowdra3d633032019-12-10 16:37:05 +0530764 if tpInstanceExists {
765 return allocID, gemPortIDs, techProfileInstance
766 }
767
768 allocIDs = appendUnique(allocIDs, allocID)
769 for _, gemPortID := range gemPortIDs {
770 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
771 }
772
Shrey Baid26912972020-04-16 21:02:31 +0530773 logger.Infow("allocated-tcont-and-gem-ports",
774 log.Fields{
775 "alloc-ids": allocIDs,
776 "gemports": allgemPortIDs,
777 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530778 // Send Tconts and GEM ports to KV store
npujarec5762e2020-01-01 14:08:48 +0530779 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000780 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530781}
782
npujarec5762e2020-01-01 14:08:48 +0530783func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530784
Shrey Baid26912972020-04-16 21:02:31 +0530785 logger.Debugw("storing-allocated-tconts-and-gem-ports-into-KV-store",
786 log.Fields{
787 "intf-id": intfID,
788 "onu-id": onuID,
789 "uni-id": uniID,
790 "alloc-id": allocID,
791 "gemport-ids": gemPortIDs,
792 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530793 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530794 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530795 logger.Errorw("error-while-uploading-allocid-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530796 }
npujarec5762e2020-01-01 14:08:48 +0530797 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530798 logger.Errorw("error-while-uploading-gemports-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530799 }
npujarec5762e2020-01-01 14:08:48 +0530800 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530801 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 +0530802 }
Shrey Baid26912972020-04-16 21:02:31 +0530803 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 -0400804 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530805 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400806 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530807}
808
809func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000810 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530811 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000812 for _, intfID := range techRange.IntfIds {
813 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400814 tpCount++
Shrey Baid26912972020-04-16 21:02:31 +0530815 logger.Debugw("init-tech-profile-done",
816 log.Fields{
817 "intf-id": intfID,
818 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530819 }
820 }
821 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400822 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530823 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530824 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800825 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530826 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
827 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530828 }
Shrey Baid26912972020-04-16 21:02:31 +0530829 logger.Infow("populated-techprofile-for-ponports-successfully",
830 log.Fields{
831 "numofTech": tpCount,
832 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
833 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530834 return nil
835}
836
npujarec5762e2020-01-01 14:08:48 +0530837func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530838 portNo uint32, uplinkClassifier map[string]interface{},
839 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000840 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700841 uplinkClassifier[PacketTagType] = SingleTag
Shrey Baid26912972020-04-16 21:02:31 +0530842 logger.Debugw("adding-upstream-data-flow",
843 log.Fields{
844 "uplinkClassifier": uplinkClassifier,
845 "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800846 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000847 Upstream, logicalFlow, allocID, gemportID, tpID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530848 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530849}
850
npujarec5762e2020-01-01 14:08:48 +0530851func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530852 portNo uint32, downlinkClassifier map[string]interface{},
853 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000854 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700855 downlinkClassifier[PacketTagType] = DoubleTag
Shrey Baid26912972020-04-16 21:02:31 +0530856 logger.Debugw("adding-downstream-data-flow",
857 log.Fields{
858 "downlinkClassifier": downlinkClassifier,
859 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400860 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
861 if vlan, exists := downlinkClassifier[VlanVid]; exists {
862 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700863 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400864 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
Shrey Baid26912972020-04-16 21:02:31 +0530865 logger.Infow("ignoring-dl-trap-device-flow-from-core",
866 log.Fields{
867 "flow": logicalFlow,
868 "device-id": f.deviceHandler.device.Id,
869 "onu-id": onuID,
870 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800871 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400872 }
873 }
874 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530875 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400876
Manikkaraj k884c1242019-04-11 16:26:42 +0530877 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700878 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400879 // vlan_vid is a uint32. must be type asserted as such or conversion fails
880 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530881 if ok {
882 downlinkAction[VlanVid] = dlClVid & 0xfff
883 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530884 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530885 "reason": "failed-to-convert-vlanid-classifier",
886 "vlan-id": VlanVid,
887 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530888 }
889
David K. Bainbridge794735f2020-02-11 21:01:37 -0800890 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000891 Downstream, logicalFlow, allocID, gemportID, tpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530892}
893
npujarec5762e2020-01-01 14:08:48 +0530894func (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 +0530895 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000896 allocID uint32, gemPortID uint32, tpID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530897 /* One of the OLT platform (Broadcom BAL) requires that symmetric
898 flows require the same flow_id to be used across UL and DL.
899 Since HSIA flow is the only symmetric flow currently, we need to
900 re-use the flow_id across both direction. The 'flow_category'
901 takes priority over flow_cookie to find any available HSIA_FLOW
902 id for the ONU.
903 */
Shrey Baid26912972020-04-16 21:02:31 +0530904 logger.Infow("adding-hsia-flow",
905 log.Fields{
906 "intf-id": intfID,
907 "onu-id": onuID,
908 "uni-id": uniID,
909 "device-id": f.deviceHandler.device.Id,
910 "classifier": classifier,
911 "action": action,
912 "direction": direction,
913 "alloc-id": allocID,
914 "gemport-id": gemPortID,
915 "logicalflow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530916 var vlanPbit uint32 = 0xff // means no pbit
Gamze Abaka724d0852020-03-18 12:10:24 +0000917 var vlanVid uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400918 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000919 vlanPbit = classifier[VlanPcp].(uint32)
Shrey Baid26912972020-04-16 21:02:31 +0530920 logger.Debugw("found-pbit-in-flow",
921 log.Fields{
922 "vlan-pbit": vlanPbit,
923 "intf-id": intfID,
924 "onu-id": onuID,
925 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800926 } else {
Shrey Baid26912972020-04-16 21:02:31 +0530927 logger.Debugw("pbit-not-found-in-flow",
928 log.Fields{
929 "vlan-pcp": VlanPcp,
930 "intf-id": intfID,
931 "onu-id": onuID,
932 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400933 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000934 if _, ok := classifier[VlanVid]; ok {
935 vlanVid = classifier[VlanVid].(uint32)
Shrey Baid26912972020-04-16 21:02:31 +0530936 log.Debugw("found-vlan-in-the-flow",
937 log.Fields{
938 "vlan-vid": vlanVid,
939 "intf-id": intfID,
940 "onu-id": onuID,
941 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000942 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700943 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530944 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +0530945 logger.Infow("flow-already-exists",
946 log.Fields{
947 "device-id": f.deviceHandler.device.Id,
948 "intf-id": intfID,
949 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800950 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530951 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000952 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530953 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530954 return olterrors.NewErrNotFound("hsia-flow-id",
955 log.Fields{
956 "direction": direction,
957 "device-id": f.deviceHandler.device.Id,
958 "intf-id": intfID,
959 "onu-id": onuID,
960 }, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530961 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800962 classifierProto, err := makeOpenOltClassifierField(classifier)
963 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530964 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530965 }
Shrey Baid26912972020-04-16 21:02:31 +0530966 logger.Debugw("created-classifier-proto",
967 log.Fields{
968 "classifier": *classifierProto,
969 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000970 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800971 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530972 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530973 }
Shrey Baid26912972020-04-16 21:02:31 +0530974 logger.Debugw("created-action-proto",
975 log.Fields{
976 "action": *actionProto,
977 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800978 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530979 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530980 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800981 log.Fields{
982 "classifier": classifier,
983 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +0530984 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800985 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530986 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700987 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
988 OnuId: int32(onuID),
989 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000990 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530991 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700992 AllocId: int32(allocID),
993 NetworkIntfId: int32(networkIntfID),
994 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530995 Classifier: classifierProto,
996 Action: actionProto,
997 Priority: int32(logicalFlow.Priority),
998 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000999 PortNo: portNo,
1000 TechProfileId: tpID,
1001 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001002 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301003 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301004 }
Shrey Baid26912972020-04-16 21:02:31 +05301005 logger.Infow("hsia-flow-added-to-device-successfully",
1006 log.Fields{"direction": direction,
1007 "device-id": f.deviceHandler.device.Id,
1008 "flow": flow,
1009 "intf-id": intfID,
1010 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001011 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
1012 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1013 flow.OnuId,
1014 flow.UniId,
1015 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301016 return olterrors.NewErrPersistence("update", "flow", flowID,
1017 log.Fields{
1018 "flow": flow,
1019 "device-id": f.deviceHandler.device.Id,
1020 "intf-id": intfID,
1021 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001022 }
1023 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301024}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001025
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001026func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1027 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1028 gemPortID uint32, tpID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301029
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301030 networkIntfID, err := getNniIntfID(classifier, action)
1031 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301032 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001033 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301034 "action": action,
1035 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001036 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301037 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301038
1039 // Clear the action map
1040 for k := range action {
1041 delete(action, k)
1042 }
1043
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001044 action[TrapToHost] = true
1045 classifier[UDPSrc] = uint32(68)
1046 classifier[UDPDst] = uint32(67)
1047 classifier[PacketTagType] = SingleTag
1048 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301049
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001050 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301051 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301052 logger.Infow("flow-exists--not-re-adding",
1053 log.Fields{
1054 "device-id": f.deviceHandler.device.Id,
1055 "intf-id": intfID,
1056 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001057 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301058 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301059
David K. Bainbridge794735f2020-02-11 21:01:37 -08001060 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 +05301061
1062 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301063 return olterrors.NewErrNotFound("flow",
1064 log.Fields{
1065 "interface-id": intfID,
1066 "gem-port": gemPortID,
1067 "cookie": flowStoreCookie,
1068 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001069 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301070 }
1071
Shrey Baid26912972020-04-16 21:02:31 +05301072 logger.Debugw("creating-ul-dhcp-flow",
1073 log.Fields{
1074 "ul_classifier": classifier,
1075 "ul_action": action,
1076 "uplinkFlowId": flowID,
1077 "intf-id": intfID,
1078 "onu-id": onuID,
1079 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301080
David K. Bainbridge794735f2020-02-11 21:01:37 -08001081 classifierProto, err := makeOpenOltClassifierField(classifier)
1082 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301083 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301084 }
Shrey Baid26912972020-04-16 21:02:31 +05301085 logger.Debugw("created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001086 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001087 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301088 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301089 }
1090
David K. Bainbridge794735f2020-02-11 21:01:37 -08001091 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001092 OnuId: int32(onuID),
1093 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301094 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001095 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001096 AllocId: int32(allocID),
1097 NetworkIntfId: int32(networkIntfID),
1098 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301099 Classifier: classifierProto,
1100 Action: actionProto,
1101 Priority: int32(logicalFlow.Priority),
1102 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001103 PortNo: portNo,
1104 TechProfileId: tpID,
1105 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001106 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301107 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001108 }
Shrey Baid26912972020-04-16 21:02:31 +05301109 logger.Infow("dhcp-ul-flow-added-to-device-successfully",
1110 log.Fields{
1111 "device-id": f.deviceHandler.device.Id,
1112 "flow-id": flowID,
1113 "intf-id": intfID,
1114 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001115 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
1116 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
1117 dhcpFlow.OnuId,
1118 dhcpFlow.UniId,
1119 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301120 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1121 log.Fields{
1122 "flow": dhcpFlow,
1123 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301124 }
1125
David K. Bainbridge794735f2020-02-11 21:01:37 -08001126 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301127}
1128
Esin Karamanae41e2b2019-12-17 18:13:13 +00001129//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301130func (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 +00001131 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32) error {
1132 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001133}
1134
1135//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301136func (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 +00001137 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string, tpID uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001138
1139 networkIntfID, err := getNniIntfID(classifier, action)
1140 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301141 return olterrors.NewErrNotFound("nni-interface-id",
1142 log.Fields{
1143 "classifier": classifier,
1144 "action": action,
1145 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001146 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001147 }
1148
1149 // Clear the action map
1150 for k := range action {
1151 delete(action, k)
1152 }
1153
1154 action[TrapToHost] = true
1155 classifier[PacketTagType] = SingleTag
1156 delete(classifier, VlanVid)
1157
1158 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301159 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301160 logger.Infow("flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001161 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001162 }
1163
npujarec5762e2020-01-01 14:08:48 +05301164 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 +00001165
1166 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301167 return olterrors.NewErrNotFound("flow-id",
1168 log.Fields{
1169 "intf-id": intfID,
1170 "oni-id": onuID,
1171 "cookie": flowStoreCookie,
1172 "flow-type": flowType,
1173 "device-id": f.deviceHandler.device.Id,
1174 "onu-id": onuID},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001175 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001176 }
1177
Shrey Baid26912972020-04-16 21:02:31 +05301178 logger.Debugw("creating-upstream-trap-flow",
1179 log.Fields{
1180 "ul_classifier": classifier,
1181 "ul_action": action,
1182 "uplinkFlowId": flowID,
1183 "flowType": flowType,
1184 "device-id": f.deviceHandler.device.Id,
1185 "intf-id": intfID,
1186 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001187
David K. Bainbridge794735f2020-02-11 21:01:37 -08001188 classifierProto, err := makeOpenOltClassifierField(classifier)
1189 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301190 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001191 }
Shrey Baid26912972020-04-16 21:02:31 +05301192 logger.Debugw("created-classifier-proto",
1193 log.Fields{
1194 "classifier": *classifierProto,
1195 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001196 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001197 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301198 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001199 }
1200
David K. Bainbridge794735f2020-02-11 21:01:37 -08001201 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001202 OnuId: int32(onuID),
1203 UniId: int32(uniID),
1204 FlowId: flowID,
1205 FlowType: Upstream,
1206 AllocId: int32(allocID),
1207 NetworkIntfId: int32(networkIntfID),
1208 GemportId: int32(gemPortID),
1209 Classifier: classifierProto,
1210 Action: actionProto,
1211 Priority: int32(logicalFlow.Priority),
1212 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001213 PortNo: portNo,
1214 TechProfileId: tpID,
1215 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001216
David K. Bainbridge794735f2020-02-11 21:01:37 -08001217 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301218 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 -08001219 }
Shrey Baid26912972020-04-16 21:02:31 +05301220 logger.Infof("%s ul-flow-added-to-device-successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001221
David K. Bainbridge794735f2020-02-11 21:01:37 -08001222 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
1223 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1224 flow.OnuId,
1225 flow.UniId,
1226 flow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301227 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 +00001228 }
1229
David K. Bainbridge794735f2020-02-11 21:01:37 -08001230 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001231}
1232
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001233// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001234func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1235 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1236 gemPortID uint32, vlanID uint32, tpID uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05301237 logger.Infow("adding-eapol-to-device",
1238 log.Fields{
1239 "intf-id": intfID,
1240 "onu-id": onuID,
1241 "port-no": portNo,
1242 "alloc-id": allocID,
1243 "gemport-id": gemPortID,
1244 "vlan-id": vlanID,
1245 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301246
1247 uplinkClassifier := make(map[string]interface{})
1248 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301249
manikkaraj kbf256be2019-03-25 00:13:48 +05301250 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001251 uplinkClassifier[EthType] = uint32(EapEthType)
1252 uplinkClassifier[PacketTagType] = SingleTag
1253 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001254 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301255 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001256 uplinkAction[TrapToHost] = true
1257 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301258 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301259 logger.Infow("flow-exists-not-re-adding", log.Fields{
1260 "device-id": f.deviceHandler.device.Id,
1261 "onu-id": onuID,
1262 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001263 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301264 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301265 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +00001266 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +05301267 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301268 return olterrors.NewErrNotFound("flow-id",
1269 log.Fields{
1270 "intf-id": intfID,
1271 "onu-id": onuID,
1272 "coookie": flowStoreCookie,
1273 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001274 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301275 }
Shrey Baid26912972020-04-16 21:02:31 +05301276 logger.Debugw("creating-ul-eapol-flow",
1277 log.Fields{
1278 "ul_classifier": uplinkClassifier,
1279 "ul_action": uplinkAction,
1280 "uplinkFlowId": uplinkFlowID,
1281 "device-id": f.deviceHandler.device.Id,
1282 "intf-id": intfID,
1283 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301284
David K. Bainbridge794735f2020-02-11 21:01:37 -08001285 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1286 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301287 return olterrors.NewErrInvalidValue(log.Fields{
1288 "classifier": uplinkClassifier,
1289 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301290 }
Shrey Baid26912972020-04-16 21:02:31 +05301291 logger.Debugw("created-classifier-proto",
1292 log.Fields{
1293 "classifier": *classifierProto,
1294 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001295 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001296 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301297 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301298 }
Shrey Baid26912972020-04-16 21:02:31 +05301299 logger.Debugw("created-action-proto",
1300 log.Fields{
1301 "action": *actionProto,
1302 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001303 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301304 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301305 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001306 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301307 "action": action,
1308 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001309 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301310 }
1311
David K. Bainbridge794735f2020-02-11 21:01:37 -08001312 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001313 OnuId: int32(onuID),
1314 UniId: int32(uniID),
1315 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001316 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001317 AllocId: int32(allocID),
1318 NetworkIntfId: int32(networkIntfID),
1319 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301320 Classifier: classifierProto,
1321 Action: actionProto,
1322 Priority: int32(logicalFlow.Priority),
1323 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001324 PortNo: portNo,
1325 TechProfileId: tpID,
1326 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001327 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301328 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001329 }
Shrey Baid26912972020-04-16 21:02:31 +05301330 logger.Infow("eapol-ul-flow-added-to-device-successfully",
1331 log.Fields{
1332 "device-id": f.deviceHandler.device.Id,
1333 "onu-id": onuID,
1334 "intf-id": intfID,
1335 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001336 flowCategory := "EAPOL"
1337 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1338 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1339 upstreamFlow.OnuId,
1340 upstreamFlow.UniId,
1341 upstreamFlow.FlowId,
1342 /* lowCategory, */
1343 flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301344 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1345 log.Fields{
1346 "flow": upstreamFlow,
1347 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301348 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001349 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301350}
1351
David K. Bainbridge794735f2020-02-11 21:01:37 -08001352func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001353 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001354
1355 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1356 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1357 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001358 if vlanID != ReservedVlan {
1359 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001360 classifier.OVid = vid
1361 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301362 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001363 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1364 vid := uint32(metadata)
1365 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001366 classifier.IVid = vid
1367 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301368 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301369 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001370 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301371 classifier.OPbits = vlanPcp
1372 } else {
1373 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301374 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001375 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1376 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1377 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1378 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001379 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001380 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1381 classifier.PktTagType = pktTagType
1382
1383 switch pktTagType {
1384 case SingleTag:
1385 case DoubleTag:
1386 case Untagged:
1387 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001388 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301389 }
1390 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001391 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301392}
1393
Gamze Abaka724d0852020-03-18 12:10:24 +00001394func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001395 var actionCmd openoltpb2.ActionCmd
1396 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301397 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001398 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301399 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001400 if _, ok := actionInfo[VlanPcp]; ok {
1401 action.Cmd.RemarkInnerPbits = true
1402 action.IPbits = actionInfo[VlanPcp].(uint32)
1403 if _, ok := actionInfo[VlanVid]; ok {
1404 action.Cmd.TranslateInnerTag = true
1405 action.IVid = actionInfo[VlanVid].(uint32)
1406 }
1407 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001408 } else if _, ok := actionInfo[PushVlan]; ok {
1409 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301410 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001411 if _, ok := actionInfo[VlanPcp]; ok {
1412 action.OPbits = actionInfo[VlanPcp].(uint32)
1413 action.Cmd.RemarkOuterPbits = true
1414 if _, ok := classifierInfo[VlanVid]; ok {
1415 action.IVid = classifierInfo[VlanVid].(uint32)
1416 action.Cmd.TranslateInnerTag = true
1417 }
1418 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001419 } else if _, ok := actionInfo[TrapToHost]; ok {
1420 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301421 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001422 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301423 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001424 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301425}
1426
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001427// getTPpath return the ETCD path for a given UNI port
1428func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uniPath string, TpID uint32) string {
1429 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301430}
1431
Gamze Abakafee36392019-10-03 11:17:24 +00001432// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301433func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1434 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001435 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1436
Gamze Abakafee36392019-10-03 11:17:24 +00001437 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301438 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301439 olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301440 // return err
1441 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001442 }
Shrey Baid26912972020-04-16 21:02:31 +05301443 log.Debugw("tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001444 }
1445 return nil
1446}
1447
1448// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301449func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001450 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001451 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001452 }
npujarec5762e2020-01-01 14:08:48 +05301453 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301454 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1455 log.Fields{
1456 "tp-id": tpID,
1457 "uni-port-name": uniPortName,
1458 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001459 }
1460 return nil
1461}
1462
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001463func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301464 if len(classifier) == 0 { // should never happen
Shrey Baid26912972020-04-16 21:02:31 +05301465 logger.Error("invalid-classfier-object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301466 return 0
1467 }
Shrey Baid26912972020-04-16 21:02:31 +05301468 logger.Debugw("generating-flow-store-cookie",
1469 log.Fields{
1470 "classifier": classifier,
1471 "gemport-id": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301472 var jsonData []byte
1473 var flowString string
1474 var err error
1475 // TODO: Do we need to marshall ??
1476 if jsonData, err = json.Marshal(classifier); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301477 logger.Error("failed-to-encode-classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301478 return 0
1479 }
1480 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001481 if gemPortID != 0 {
1482 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301483 }
1484 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001485 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301486 hash := big.NewInt(0)
1487 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301488 generatedHash := hash.Uint64()
Shrey Baid26912972020-04-16 21:02:31 +05301489 logger.Debugw("hash-generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301490 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301491}
1492
npujarec5762e2020-01-01 14:08:48 +05301493func (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 +05301494 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001495 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001496 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1497 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1498 */
1499 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001500 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001501 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001502 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001503 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001504 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301505 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001506 if existingFlows != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301507 logger.Debugw("flow-exists-for-given-flowID--appending-it-to-current-flow",
1508 log.Fields{
1509 "flow-id": flow.FlowId,
1510 "device-id": f.deviceHandler.device.Id,
1511 "intf-id": intfID,
1512 "onu-id": flow.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001513 //for _, f := range *existingFlows {
1514 // flows = append(flows, f)
1515 //}
1516 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001517 }
Shrey Baid26912972020-04-16 21:02:31 +05301518 logger.Debugw("updated-flows-for-given-flowID-and-onuid",
1519 log.Fields{
1520 "updatedflow": flows,
1521 "flow-id": flow.FlowId,
1522 "onu-id": flow.OnuId,
1523 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +05301524 return &flows
1525}
1526
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001527//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1528// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1529// var intfId uint32
1530// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1531// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1532// */
1533// if flow.AccessIntfId != -1 {
1534// intfId = uint32(flow.AccessIntfId)
1535// } else {
1536// intfId = uint32(flow.NetworkIntfId)
1537// }
1538// // Get existing flows matching flowid for given subscriber from KV store
1539// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1540// if existingFlows != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001541// logger.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001542// for _, f := range *existingFlows {
1543// flows = append(flows, f)
1544// }
1545// }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001546// 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 -04001547// return &flows
1548//}
1549
npujarec5762e2020-01-01 14:08:48 +05301550func (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 +05301551 logger.Debugw("storing-flow(s)-into-kv-store", log.Fields{
1552 "flow-id": flowID,
1553 "device-id": f.deviceHandler.device.Id,
1554 "intf-id": intfID,
1555 "onu-id": onuID})
npujarec5762e2020-01-01 14:08:48 +05301556 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301557 logger.Warnw("error-while-storing-flow-into-kv-store", log.Fields{
1558 "device-id": f.deviceHandler.device.Id,
1559 "onu-id": onuID,
1560 "intf-id": intfID,
1561 "flow-id": flowID})
manikkaraj k17652a72019-05-06 09:06:36 -04001562 return err
1563 }
Shrey Baid26912972020-04-16 21:02:31 +05301564 logger.Infow("stored-flow(s)-into-kv-store-successfully!", log.Fields{
1565 "device-id": f.deviceHandler.device.Id,
1566 "onu-id": onuID,
1567 "intf-id": intfID,
1568 "flow-id": flowID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301569 return nil
1570}
1571
David K. Bainbridge794735f2020-02-11 21:01:37 -08001572func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001573
1574 var intfID uint32
1575 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1576 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1577 */
1578 if deviceFlow.AccessIntfId != -1 {
1579 intfID = uint32(deviceFlow.AccessIntfId)
1580 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001581 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001582 intfID = uint32(deviceFlow.NetworkIntfId)
1583 }
1584
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001585 logger.Debugw("sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301586 "flow": *deviceFlow,
1587 "device-id": f.deviceHandler.device.Id,
1588 "intf-id": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301589 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001590
1591 st, _ := status.FromError(err)
1592 if st.Code() == codes.AlreadyExists {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001593 logger.Debug("flow-already-exists", log.Fields{
1594 "err": err,
1595 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301596 "device-id": f.deviceHandler.device.Id,
1597 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001598 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301599 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001600
1601 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301602 logger.Errorw("failed-to-add-flow-to-device",
1603 log.Fields{"err": err,
1604 "device-flow": deviceFlow,
1605 "device-id": f.deviceHandler.device.Id,
1606 "intf-id": intfID})
npujarec5762e2020-01-01 14:08:48 +05301607 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001608 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001609 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301610 if deviceFlow.GemportId != -1 {
1611 // No need to register the flow if it is a trap on nni flow.
npujarec5762e2020-01-01 14:08:48 +05301612 f.registerFlow(ctx, logicalFlow, deviceFlow)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301613 }
Shrey Baid26912972020-04-16 21:02:31 +05301614 logger.Infow("flow-added-to-device-successfully ",
1615 log.Fields{
1616 "flow": *deviceFlow,
1617 "device-id": f.deviceHandler.device.Id,
1618 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001619 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001620}
1621
David K. Bainbridge794735f2020-02-11 21:01:37 -08001622func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) error {
Shrey Baid26912972020-04-16 21:02:31 +05301623 logger.Debugw("sending-flow-to-device-via-grpc",
1624 log.Fields{
1625 "flow": *deviceFlow,
1626 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001627 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1628 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001629 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Shrey Baid26912972020-04-16 21:02:31 +05301630 logger.Warnw("can-not-remove-flow-from-device--unreachable",
1631 log.Fields{
1632 "err": err,
1633 "deviceFlow": deviceFlow,
1634 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001635 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001636 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001637 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001638 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001639
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001640 }
Shrey Baid26912972020-04-16 21:02:31 +05301641 logger.Infow("flow-removed-from-device-successfully ",
1642 log.Fields{
1643 "flow": *deviceFlow,
1644 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001645 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301646}
1647
1648/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1649 //update core flows_proxy : flows_proxy.update('/', flows)
1650}
1651
1652func generateStoredId(flowId uint32, direction string)uint32{
1653
David K. Bainbridge82efc492019-09-04 09:57:11 -07001654 if direction == Upstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001655 logger.Debug("Upstream flow shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301656 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001657 }else if direction == Downstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001658 logger.Debug("Downstream flow not shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301659 return flowId
1660 }else{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001661 logger.Errorw("Unrecognized direction",log.Fields{"direction": direction})
manikkaraj kbf256be2019-03-25 00:13:48 +05301662 return flowId
1663 }
1664}
1665
1666*/
1667
David K. Bainbridge794735f2020-02-11 21:01:37 -08001668func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001669
1670 classifierInfo := make(map[string]interface{})
1671 actionInfo := make(map[string]interface{})
1672
1673 classifierInfo[EthType] = uint32(LldpEthType)
1674 classifierInfo[PacketTagType] = Untagged
1675 actionInfo[TrapToHost] = true
1676
1677 // LLDP flow is installed to trap LLDP packets on the NNI port.
1678 // We manage flow_id resource pool on per PON port basis.
1679 // Since this situation is tricky, as a hack, we pass the NNI port
1680 // index (network_intf_id) as PON port Index for the flow_id resource
1681 // pool. Also, there is no ONU Id available for trapping LLDP packets
1682 // on NNI port, use onu_id as -1 (invalid)
1683 // ****************** CAVEAT *******************
1684 // This logic works if the NNI Port Id falls within the same valid
1685 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1686 // we need to have a re-look at this.
1687 // *********************************************
1688
1689 var onuID = -1
1690 var uniID = -1
1691 var gemPortID = -1
1692
David K. Bainbridge794735f2020-02-11 21:01:37 -08001693 networkInterfaceID, err := IntfIDFromNniPortNum(portNo)
1694 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301695 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001696 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001697 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301698 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05301699 logger.Infow("flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001700 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001701 }
npujarec5762e2020-01-01 14:08:48 +05301702 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001703
1704 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301705 return olterrors.NewErrNotFound("flow-id",
1706 log.Fields{
1707 "interface-id": networkInterfaceID,
1708 "onu-id": onuID,
1709 "uni-id": uniID,
1710 "gem-port-id": gemPortID,
1711 "cookie": flowStoreCookie,
1712 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001713 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001714 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001715 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1716 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301717 return olterrors.NewErrInvalidValue(
1718 log.Fields{
1719 "classifier": classifierInfo,
1720 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001721 }
Shrey Baid26912972020-04-16 21:02:31 +05301722 logger.Debugw("created-classifier-proto",
1723 log.Fields{
1724 "classifier": *classifierProto,
1725 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001726 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001727 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301728 return olterrors.NewErrInvalidValue(
1729 log.Fields{
1730 "action": actionInfo,
1731 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001732 }
Shrey Baid26912972020-04-16 21:02:31 +05301733 logger.Debugw("created-action-proto",
1734 log.Fields{
1735 "action": *actionProto,
1736 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001737
1738 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1739 OnuId: int32(onuID), // OnuId not required
1740 UniId: int32(uniID), // UniId not used
1741 FlowId: flowID,
1742 FlowType: Downstream,
1743 NetworkIntfId: int32(networkInterfaceID),
1744 GemportId: int32(gemPortID),
1745 Classifier: classifierProto,
1746 Action: actionProto,
1747 Priority: int32(flow.Priority),
1748 Cookie: flow.Cookie,
1749 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001750 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301751 return olterrors.NewErrFlowOp("add", flowID,
1752 log.Fields{
1753 "flow": downstreamflow,
1754 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001755 }
Shrey Baid26912972020-04-16 21:02:31 +05301756 logger.Infow("lldp-trap-on-nni-flow-added-to-device-successfully",
1757 log.Fields{
1758 "device-id": f.deviceHandler.device.Id,
1759 "onu-id": onuID,
1760 "flow-id": flowID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001761 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1762 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1763 int32(onuID),
1764 int32(uniID),
1765 flowID, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301766 return olterrors.NewErrPersistence("update", "flow", flowID,
1767 log.Fields{
1768 "flow": downstreamflow,
1769 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001770 }
1771 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301772}
1773
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001774func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1775 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001776}
1777
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001778//getOnuDevice to fetch onu from cache or core.
1779func (f *OpenOltFlowMgr) getOnuDevice(intfID uint32, onuID uint32) (*OnuDevice, error) {
1780 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1781 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1782 if !ok {
Shrey Baid26912972020-04-16 21:02:31 +05301783 logger.Debugw("couldnt-find-onu-in-cache",
1784 log.Fields{
1785 "intf-id": intfID,
1786 "onu-id": onuID,
1787 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001788 onuDevice, err := f.getChildDevice(intfID, onuID)
1789 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301790 return nil, olterrors.NewErrNotFound("onu-child-device",
1791 log.Fields{
1792 "onu-id": onuID,
1793 "intf-id": intfID,
1794 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001795 }
1796 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1797 //better to ad the device to cache here.
1798 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1799 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301800 logger.Debugw("found-onu-in-cache",
1801 log.Fields{
1802 "intf-id": intfID,
1803 "onu-id": onuID,
1804 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001805 }
1806
1807 return onuDev.(*OnuDevice), nil
1808}
1809
1810//getChildDevice to fetch onu
1811func (f *OpenOltFlowMgr) getChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
Shrey Baid26912972020-04-16 21:02:31 +05301812 logger.Infow("GetChildDevice",
1813 log.Fields{
1814 "pon-port": intfID,
1815 "onu-id": onuID,
1816 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001817 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001818 onuDevice, err := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
1819 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301820 return nil, olterrors.NewErrNotFound("onu",
1821 log.Fields{
1822 "interface-id": parentPortNo,
1823 "onu-id": onuID,
1824 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001825 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301826 }
Shrey Baid26912972020-04-16 21:02:31 +05301827 logger.Infow("successfully-received-child-device-from-core",
1828 log.Fields{
1829 "device-id": f.deviceHandler.device.Id,
1830 "child_device_id": onuDevice.Id,
1831 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301832 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301833}
1834
1835func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Shrey Baid26912972020-04-16 21:02:31 +05301836 logger.Info("unimplemented-flow %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301837 return nil
1838}
1839
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001840func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
Shrey Baid26912972020-04-16 21:02:31 +05301841 logger.Info("unimplemented-device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301842}
1843
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001844func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001845 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001846 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001847 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001848 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001849}
1850
Girish Gowdra6b130582019-11-20 16:45:20 +05301851func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001852 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301853 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301854 logger.Debugw("couldnt-find-onu-child-device",
1855 log.Fields{
1856 "intf-id": intfID,
1857 "onu-id": onuID,
1858 "uni-id": uniID,
1859 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001860 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301861 }
1862
1863 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Shrey Baid26912972020-04-16 21:02:31 +05301864 logger.Debugw("sending-gem-port-delete-to-openonu-adapter",
1865 log.Fields{
1866 "msg": *delGemPortMsg,
1867 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301868 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1869 delGemPortMsg,
1870 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301871 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001872 onuDev.deviceType,
1873 onuDev.deviceID,
1874 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301875 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1876 log.Fields{
1877 "from-adapter": f.deviceHandler.device.Type,
1878 "to-adapter": onuDev.deviceType,
1879 "onu-id": onuDev.deviceID,
1880 "proxyDeviceID": onuDev.proxyDeviceID,
1881 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301882 }
Shrey Baid26912972020-04-16 21:02:31 +05301883 logger.Infow("success-sending-del-gem-port-to-onu-adapter",
1884 log.Fields{
1885 "msg": delGemPortMsg,
1886 "from-adapter": f.deviceHandler.device.Type,
1887 "to-adapter": onuDev.deviceType,
1888 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301889 return nil
1890}
1891
1892func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001893 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301894 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301895 logger.Warnw("couldnt-find-onu-child-device",
1896 log.Fields{
1897 "intf-id": intfID,
1898 "onu-id": onuID,
1899 "uni-id": uniID,
1900 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001901 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301902 }
1903
1904 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Shrey Baid26912972020-04-16 21:02:31 +05301905 logger.Debugw("sending-tcont-delete-to-openonu-adapter",
1906 log.Fields{
1907 "msg": *delTcontMsg,
1908 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301909 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1910 delTcontMsg,
1911 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301912 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001913 onuDev.deviceType,
1914 onuDev.deviceID,
1915 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301916 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1917 log.Fields{
1918 "from-adapter": f.deviceHandler.device.Type,
1919 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1920 "proxyDeviceID": onuDev.proxyDeviceID,
1921 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301922 }
Shrey Baid26912972020-04-16 21:02:31 +05301923 logger.Infow("success-sending-del-tcont-to-onu-adapter",
1924 log.Fields{
1925 "msg": delTcontMsg,
1926 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301927 return nil
1928}
1929
Girish Gowdra3d633032019-12-10 16:37:05 +05301930func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1931 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1932 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1933 if val.(int) > 0 {
1934 pnFlDels := val.(int) - 1
1935 if pnFlDels > 0 {
Shrey Baid26912972020-04-16 21:02:31 +05301936 logger.Debugw("flow-delete-succeeded--more-pending",
1937 log.Fields{
1938 "intf": Intf,
1939 "onu-id": onuID,
1940 "uni-id": uniID,
1941 "currpendingflowcnt": pnFlDels,
1942 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301943 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1944 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301945 logger.Debugw("all-pending-flow-deletes-handled--removing-entry-from-map",
1946 log.Fields{
1947 "intf": Intf,
1948 "onu-id": onuID,
1949 "uni-id": uniID,
1950 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301951 f.pendingFlowDelete.Delete(pnFlDelKey)
1952 }
1953 }
1954 } else {
Shrey Baid26912972020-04-16 21:02:31 +05301955 logger.Debugw("no-pending-delete-flows-found",
1956 log.Fields{
1957 "intf": Intf,
1958 "onu-id": onuID,
1959 "uni-id": uniID,
1960 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301961
1962 }
1963
1964}
1965
Girish Gowdrac3037402020-01-22 20:29:53 +05301966// Once the gemport is released for a given onu, it also has to be cleared from local cache
1967// which was used for deriving the gemport->logicalPortNo during packet-in.
1968// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1969// is conveyed to ONOS during packet-in OF message.
1970func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001971
1972 f.onuGemInfoLock[intfID].Lock()
1973 defer f.onuGemInfoLock[intfID].Unlock()
1974
Shrey Baid26912972020-04-16 21:02:31 +05301975 logger.Infow("deleting-gem-from-local-cache",
1976 log.Fields{
1977 "gem": gemPortID,
1978 "intf-id": intfID,
1979 "onu-id": onuID,
1980 "device-id": f.deviceHandler.device.Id,
1981 "onu-gem": f.onuGemInfo[intfID]})
Girish Gowdrac3037402020-01-22 20:29:53 +05301982 onugem := f.onuGemInfo[intfID]
serkant.uluderya96af4932020-02-20 16:58:48 -08001983 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301984 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001985 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301986 // If the gemport is found, delete it from local cache.
1987 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001988 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1989 onugem[i] = onu
Shrey Baid26912972020-04-16 21:02:31 +05301990 logger.Infow("removed-gemport-from-local-cache",
1991 log.Fields{
1992 "intf-id": intfID,
1993 "onu-id": onuID,
1994 "deletedgemport-id": gemPortID,
1995 "gemports": onu.GemPorts,
1996 "device-id": f.deviceHandler.device.Id})
Girish Gowdrac3037402020-01-22 20:29:53 +05301997 break
1998 }
1999 }
2000 break
2001 }
2002 }
2003}
2004
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302005//clearResources clears pon resources in kv store and the device
npujarec5762e2020-01-01 14:08:48 +05302006func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302007 gemPortID int32, flowID uint32, flowDirection string,
2008 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002009
Chaitrashree G S90a17952019-11-14 21:51:21 -05002010 tpID, err := getTpIDFromFlow(flow)
2011 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302012 return olterrors.NewErrNotFound("tp-id",
2013 log.Fields{
2014 "flow": flow,
2015 "intf": Intf,
2016 "onu-id": onuID,
2017 "uni-id": uniID,
2018 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002019 }
Gamze Abakafee36392019-10-03 11:17:24 +00002020
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002021 if len(updatedFlows) >= 0 {
2022 // There are still flows referencing the same flow_id.
2023 // So the flow should not be freed yet.
2024 // For ex: Case of HSIA where same flow is shared
2025 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00002026 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302027 olterrors.NewErrPersistence("update", "flow", flowID,
2028 log.Fields{
2029 "flow": updatedFlows,
2030 "device-id": f.deviceHandler.device.Id}, err).Log()
Girish Kumarf26e4882020-03-05 06:49:10 +00002031 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002032 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05302033 // Do this for subscriber flows only (not trap from NNI flows)
2034 if onuID != -1 && uniID != -1 {
2035 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
2036 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Shrey Baid26912972020-04-16 21:02:31 +05302037 logger.Debugw("creating-entry-for-pending-flow-delete",
2038 log.Fields{
2039 "flow-id": flowID,
2040 "intf": Intf,
2041 "onu-id": onuID,
2042 "uni-id": uniID,
2043 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302044 f.pendingFlowDelete.Store(pnFlDelKey, 1)
2045 } else {
2046 pnFlDels := val.(int) + 1
Shrey Baid26912972020-04-16 21:02:31 +05302047 logger.Debugw("updating-flow-delete-entry",
2048 log.Fields{
2049 "flow-id": flowID,
2050 "intf": Intf,
2051 "onu-id": onuID,
2052 "uni-id": uniID,
2053 "currPendingFlowCnt": pnFlDels,
2054 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302055 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
2056 }
2057
2058 defer f.deletePendingFlows(Intf, onuID, uniID)
2059 }
2060
Shrey Baid26912972020-04-16 21:02:31 +05302061 logger.Debugw("releasing-flow-id-to-resource-manager",
2062 log.Fields{
2063 "Intf": Intf,
2064 "onu-id": onuID,
2065 "uni-id": uniID,
2066 "flow-id": flowID,
2067 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302068 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002069
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002070 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302071 tpPath := f.getTPpath(Intf, uni, tpID)
Shrey Baid26912972020-04-16 21:02:31 +05302072 logger.Debugw("getting-techprofile-instance-for-subscriber",
2073 log.Fields{
2074 "TP-PATH": tpPath,
2075 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302076 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00002077 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +05302078 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
2079 log.Fields{
2080 "tp-id": tpID,
2081 "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002082 }
2083
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302084 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00002085 if f.isGemPortUsedByAnotherFlow(gemPK) {
2086 flowIDs := f.flowsUsedByGemPort[gemPK]
2087 for i, flowIDinMap := range flowIDs {
2088 if flowIDinMap == flowID {
2089 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302090 // everytime flowsUsedByGemPort cache is updated the same should be updated
2091 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002092 f.flowsUsedByGemPort[gemPK] = flowIDs
npujarec5762e2020-01-01 14:08:48 +05302093 f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00002094 break
2095 }
2096 }
Shrey Baid26912972020-04-16 21:02:31 +05302097 logger.Debugw("gem-port-id-is-still-used-by-other-flows",
2098 log.Fields{
2099 "gemport-id": gemPortID,
2100 "usedByFlows": flowIDs,
2101 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302102 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00002103 }
Shrey Baid26912972020-04-16 21:02:31 +05302104 logger.Debugf("gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05302105 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002106 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
2107 // 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 +05302108 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Girish Gowdrac3037402020-01-22 20:29:53 +05302109 f.deleteGemPortFromLocalCache(Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002110 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302111 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
2112 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002113 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05302114 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
2115 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002116 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05302117 // Delete the gem port on the ONU.
2118 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302119 logger.Errorw("error-processing-delete-gem-port-towards-onu",
2120 log.Fields{
2121 "err": err,
2122 "intf": Intf,
2123 "onu-id": onuID,
2124 "uni-id": uniID,
2125 "device-id": f.deviceHandler.device.Id,
2126 "gemport-id": gemPortID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302127 }
Gamze Abakafee36392019-10-03 11:17:24 +00002128
npujarec5762e2020-01-01 14:08:48 +05302129 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002130 if !ok {
npujarec5762e2020-01-01 14:08:48 +05302131 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
2132 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
2133 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
2134 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
2135 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302136 // Delete the TCONT on the ONU.
2137 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302138 logger.Errorw("error-processing-delete-tcont-towards-onu",
2139 log.Fields{
2140 "intf": Intf,
2141 "onu-id": onuID,
2142 "uni-id": uniID,
2143 "device-id": f.deviceHandler.device.Id,
2144 "alloc-id": techprofileInst.UsScheduler.AllocID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302145 }
Gamze Abakafee36392019-10-03 11:17:24 +00002146 }
2147 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002148 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302149 return nil
2150}
2151
David K. Bainbridge794735f2020-02-11 21:01:37 -08002152// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302153func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302154
Shrey Baid26912972020-04-16 21:02:31 +05302155 logger.Infow("clear-flow-from-resource-manager",
2156 log.Fields{
2157 "flowDirection": flowDirection,
2158 "flow": *flow,
2159 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002160
2161 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05302162 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002163 return
2164 }
2165
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302166 var updatedFlows []rsrcMgr.FlowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302167 classifierInfo := make(map[string]interface{})
2168
2169 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
2170 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002171 logger.Error(err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302172 return
2173 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302174
David K. Bainbridge794735f2020-02-11 21:01:37 -08002175 onuID := int32(onu)
2176 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302177
2178 for _, field := range flows.GetOfbFields(flow) {
2179 if field.Type == flows.IP_PROTO {
2180 classifierInfo[IPProto] = field.GetIpProto()
Shrey Baid26912972020-04-16 21:02:31 +05302181 logger.Debugw("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302182 }
2183 }
Shrey Baid26912972020-04-16 21:02:31 +05302184 logger.Infow("extracted-access-info-from-flow-to-be-deleted",
2185 log.Fields{
2186 "ponIntf": Intf,
2187 "onu-id": onuID,
2188 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302189
2190 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2191 onuID = -1
2192 uniID = -1
Shrey Baid26912972020-04-16 21:02:31 +05302193 logger.Debug("trap-on-nni-flow-set-oni--uni-to- -1")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002194 Intf, err = IntfIDFromNniPortNum(inPort)
2195 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002196 logger.Errorw("invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002197 log.Fields{
2198 "port-number": inPort,
2199 "error": err})
2200 return
2201 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302202 }
npujarec5762e2020-01-01 14:08:48 +05302203 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002204 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302205 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302206 if flowInfo == nil {
Shrey Baid26912972020-04-16 21:02:31 +05302207 logger.Debugw("no-flowinfo-found-in-kv-store",
2208 log.Fields{
2209 "intf": Intf,
2210 "onu-id": onuID,
2211 "uni-id": uniID,
2212 "flow-id": flowID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302213 return
2214 }
2215 updatedFlows = nil
2216 for _, flow := range *flowInfo {
2217 updatedFlows = append(updatedFlows, flow)
2218 }
2219
2220 for i, storedFlow := range updatedFlows {
2221 if flow.Id == storedFlow.LogicalFlowID {
2222 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Shrey Baid26912972020-04-16 21:02:31 +05302223 logger.Debugw("flow-to-be-deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002224 // DKB
2225 if err = f.removeFlowFromDevice(&removeFlowMessage); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002226 logger.Errorw("failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002227 return
2228 }
Shrey Baid26912972020-04-16 21:02:31 +05302229 logger.Info("flow-removed-from-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002230 //Remove the Flow from FlowInfo
2231 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
2232 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
2233 flowID, flowDirection, portNum, updatedFlows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302234 logger.Error("failed-to-clear-resources-for-flow",
2235 log.Fields{
2236 "flow": storedFlow,
2237 "device-id": f.deviceHandler.device.Id,
2238 "flow-id": flowID,
2239 "onu-id": onuID,
2240 "intf": Intf})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302241 return
2242 }
2243 }
2244 }
2245 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002246}
2247
Esin Karamanccb714b2019-11-29 15:02:06 +00002248//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
2249// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05302250func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002251 classifierInfo := make(map[string]interface{})
2252 formulateClassifierInfoFromFlow(classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00002253 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002254
2255 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302256 logger.Warnw("no-inport-found--cannot-release-resources-of-the-multicast-flow", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002257 return
2258 }
2259
Esin Karamanccb714b2019-11-29 15:02:06 +00002260 var onuID = int32(NoneOnuID)
2261 var uniID = int32(NoneUniID)
2262 var flowID uint32
2263 var updatedFlows []rsrcMgr.FlowInfo
2264
npujarec5762e2020-01-01 14:08:48 +05302265 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002266
2267 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302268 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002269 if flowInfo == nil {
Shrey Baid26912972020-04-16 21:02:31 +05302270 logger.Debugw("no-multicast-flowinfo-found-in-the-kv-store",
2271 log.Fields{
2272 "intf": networkInterfaceID,
2273 "onu-id": onuID,
2274 "uni-id": uniID,
2275 "flow-id": flowID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002276 continue
2277 }
2278 updatedFlows = nil
2279 for _, flow := range *flowInfo {
2280 updatedFlows = append(updatedFlows, flow)
2281 }
2282 for i, storedFlow := range updatedFlows {
2283 if flow.Id == storedFlow.LogicalFlowID {
2284 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Shrey Baid26912972020-04-16 21:02:31 +05302285 logger.Debugw("multicast-flow-to-be-deleted",
2286 log.Fields{
2287 "flow": storedFlow,
2288 "flow-id": flow.Id,
2289 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002290 //remove from device
David K. Bainbridge794735f2020-02-11 21:01:37 -08002291 if err := f.removeFlowFromDevice(&removeFlowMessage); err != nil {
2292 // DKB
Girish Kumar2ad402b2020-03-20 19:45:12 +00002293 logger.Errorw("failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002294 log.Fields{
2295 "flow-id": flow.Id,
2296 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002297 return
2298 }
Shrey Baid26912972020-04-16 21:02:31 +05302299 logger.Infow("multicast-flow-removed-from-device-successfully", log.Fields{"flow-id": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002300 //Remove the Flow from FlowInfo
2301 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05302302 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302303 logger.Errorw("failed-to-delete-multicast-flow-from-the-kv-store",
2304 log.Fields{"flow": storedFlow,
2305 "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002306 return
2307 }
2308 //release flow id
Shrey Baid26912972020-04-16 21:02:31 +05302309 logger.Debugw("releasing-multicast-flow-id",
2310 log.Fields{"flow-id": flowID,
2311 "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05302312 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002313 }
2314 }
2315 }
2316}
2317
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002318//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002319func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Shrey Baid26912972020-04-16 21:02:31 +05302320 logger.Infow("removing-flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302321 var direction string
2322 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002323
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302324 for _, action := range flows.GetActions(flow) {
2325 if action.Type == flows.OUTPUT {
2326 if out := action.GetOutput(); out != nil {
2327 actionInfo[Output] = out.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002328 logger.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302329 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302330 logger.Error("invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002331 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002332 }
2333 }
2334 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002335
2336 if flows.HasGroup(flow) {
2337 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07002338 f.clearFlowFromResourceManager(ctx, flow, direction)
2339 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002340 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302341 direction = Upstream
2342 } else {
2343 direction = Downstream
2344 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302345
Girish Gowdracefae192020-03-19 18:14:10 -07002346 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(flow, direction)
2347 if err != nil {
2348 return err
2349 }
2350
2351 userKey := tpLockKey{intfID, onuID, uniID}
2352
2353 // Serialize flow removes on a per subscriber basis
2354 if f.perUserFlowHandleLock.TryLock(userKey) {
2355 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
2356 f.perUserFlowHandleLock.Unlock(userKey)
2357 } else {
2358 // Ideally this should never happen
Shrey Baid26912972020-04-16 21:02:31 +05302359 logger.Errorw("failed-to-acquire-lock-to-remove-flow--remove-aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07002360 return errors.New("failed-to-acquire-per-user-lock")
2361 }
2362
2363 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002364}
2365
Girish Gowdra3d633032019-12-10 16:37:05 +05302366func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
2367 uniID uint32, ch chan bool) {
2368 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2369 for {
2370 select {
2371 case <-time.After(20 * time.Millisecond):
2372 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Shrey Baid26912972020-04-16 21:02:31 +05302373 logger.Debug("pending-flow-deletes-completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05302374 ch <- true
2375 return
2376 }
2377 case <-ctx.Done():
Shrey Baid26912972020-04-16 21:02:31 +05302378 logger.Error("flow-delete-wait-handler-routine-canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05302379 return
2380 }
2381 }
2382}
2383
Esin Karamanae41e2b2019-12-17 18:13:13 +00002384//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2385func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2386 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2387 if ethType, ok := classifierInfo[EthType]; ok {
2388 if ethType.(uint32) == IPv4EthType {
2389 if ipProto, ok := classifierInfo[IPProto]; ok {
2390 if ipProto.(uint32) == IgmpProto {
2391 return true
2392 }
2393 }
2394 }
2395 }
2396 }
2397 return false
2398}
2399
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002400// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302401// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002402func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002403 classifierInfo := make(map[string]interface{})
2404 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002405 var UsMeterID uint32
2406 var DsMeterID uint32
2407
Shrey Baid26912972020-04-16 21:02:31 +05302408 logger.Infow("adding-flow",
2409 log.Fields{
2410 "flow": flow,
2411 "flowmetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002412 formulateClassifierInfoFromFlow(classifierInfo, flow)
2413
2414 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
2415 if err != nil {
2416 // Error logging is already done in the called function
2417 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002418 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302419 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002420
Esin Karamanccb714b2019-11-29 15:02:06 +00002421 if flows.HasGroup(flow) {
2422 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002423 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002424 }
2425
manikkaraj k17652a72019-05-06 09:06:36 -04002426 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00002427 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
2428 if err != nil {
2429 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002430 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002431 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002432
Shrey Baid26912972020-04-16 21:02:31 +05302433 logger.Debugw("flow-ports",
2434 log.Fields{
2435 "classifierinfo_inport": classifierInfo[InPort],
2436 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002437 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002438
Humera Kouser94d7a842019-08-25 19:04:32 -04002439 if ethType, ok := classifierInfo[EthType]; ok {
2440 if ethType.(uint32) == LldpEthType {
Shrey Baid26912972020-04-16 21:02:31 +05302441 logger.Info("adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002442 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002443 }
2444 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002445 if ipProto, ok := classifierInfo[IPProto]; ok {
2446 if ipProto.(uint32) == IPProtoDhcp {
2447 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302448 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002449 logger.Debug("trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002450 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002451 }
2452 }
2453 }
2454 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002455 if isIgmpTrapDownstreamFlow(classifierInfo) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002456 logger.Debug("trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002457 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002458 }
A R Karthick1f85b802019-10-11 05:06:05 +00002459
2460 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
npujarec5762e2020-01-01 14:08:48 +05302461 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002462
Chaitrashree G S90a17952019-11-14 21:51:21 -05002463 TpID, err := getTpIDFromFlow(flow)
2464 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302465 return olterrors.NewErrNotFound("tpid-for-flow",
2466 log.Fields{
2467 "flow": flow,
2468 "intf-id": IntfID,
2469 "onu-id": onuID,
2470 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002471 }
Shrey Baid26912972020-04-16 21:02:31 +05302472 logger.Debugw("tpid-for-this-subcriber",
2473 log.Fields{
2474 "tp-id": TpID,
2475 "intf-id": intfID,
2476 "onu-id": onuID,
2477 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002478 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002479 UsMeterID = flows.GetMeterIdFromFlow(flow)
Shrey Baid26912972020-04-16 21:02:31 +05302480 logger.Debugw("upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002481 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002482 DsMeterID = flows.GetMeterIdFromFlow(flow)
Shrey Baid26912972020-04-16 21:02:31 +05302483 logger.Debugw("downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002484
2485 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302486
2487 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2488 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Shrey Baid26912972020-04-16 21:02:31 +05302489 logger.Debugw("no-pending-flows-found--going-ahead-with-flow-install",
2490 log.Fields{
2491 "intf-id": intfID,
2492 "onu-id": onuID,
2493 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302494 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302495 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05302496 pendingFlowDelComplete := make(chan bool)
2497 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
2498 select {
2499 case <-pendingFlowDelComplete:
Shrey Baid26912972020-04-16 21:02:31 +05302500 logger.Debugw("all-pending-flow-deletes-completed",
2501 log.Fields{
2502 "intf-id": intfID,
2503 "onu-id": onuID,
2504 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302505 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302506
2507 case <-time.After(10 * time.Second):
Shrey Baid26912972020-04-16 21:02:31 +05302508 return olterrors.NewErrTimeout("pending-flow-deletes",
2509 log.Fields{
2510 "intf-id": intfID,
2511 "onu-id": onuID,
2512 "uni-id": uniID}, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +05302513 }
2514 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002515 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002516}
2517
Esin Karamanccb714b2019-11-29 15:02:06 +00002518// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002519func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002520 classifierInfo[PacketTagType] = DoubleTag
Shrey Baid26912972020-04-16 21:02:31 +05302521 logger.Debugw("add-multicast-flow", log.Fields{
2522 "classifier-info": classifierInfo,
2523 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002524
Esin Karaman65409d82020-03-18 10:58:18 +00002525 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002526 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002527 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002528 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002529 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
2530 //otherwise, classification is based on ipv4_dst by default.
2531 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
2532 mcastFlowClassificationByEthDst := false
2533
2534 if mcastFlowClassificationByEthDst {
2535 //replace ipDst with ethDst
2536 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
2537 flows.IsMulticastIp(ipv4Dst.(uint32)) {
2538 // replace ipv4_dst classifier with eth_dst
2539 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
2540 delete(classifierInfo, Ipv4Dst)
2541 classifierInfo[EthDst] = multicastMac
Shrey Baid26912972020-04-16 21:02:31 +05302542 logger.Debugw("multicast-ip-to-mac-conversion-success",
2543 log.Fields{
2544 "ip:": ipv4Dst.(uint32),
2545 "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002546 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002547 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002548 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002549
David K. Bainbridge794735f2020-02-11 21:01:37 -08002550 onuID := NoneOnuID
2551 uniID := NoneUniID
2552 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00002553
David K. Bainbridge794735f2020-02-11 21:01:37 -08002554 flowStoreCookie := getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302555 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05302556 logger.Infow("multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002557 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002558 }
npujarec5762e2020-01-01 14:08:48 +05302559 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00002560 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302561 return olterrors.NewErrNotFound("multicast-flow-id",
2562 log.Fields{
2563 "interface-id": networkInterfaceID,
2564 "onu-id": onuID,
2565 "uni-id": uniID,
2566 "gem-port-id": gemPortID,
2567 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002568 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002569 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002570 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2571 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002572 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002573 }
2574 groupID := actionInfo[GroupID].(uint32)
2575 multicastFlow := openoltpb2.Flow{
2576 FlowId: flowID,
2577 FlowType: Multicast,
2578 NetworkIntfId: int32(networkInterfaceID),
2579 GroupId: groupID,
2580 Classifier: classifierProto,
2581 Priority: int32(flow.Priority),
2582 Cookie: flow.Cookie}
2583
David K. Bainbridge794735f2020-02-11 21:01:37 -08002584 if err = f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002585 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002586 }
Shrey Baid26912972020-04-16 21:02:31 +05302587 logger.Info("multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002588 //get cached group
2589 group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true)
2590 if err == nil {
2591 //calling groupAdd to set group members after multicast flow creation
Andrea Campanellac63bba92020-03-10 17:01:04 +01002592 if err = f.ModifyGroup(ctx, group); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002593 //cached group can be removed now
2594 f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002595 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002596 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002597 }
2598 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002599
2600 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2601 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2602 int32(onuID),
2603 int32(uniID),
2604 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002605 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002606 }
2607 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002608}
2609
Esin Karaman65409d82020-03-18 10:58:18 +00002610//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2611func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2612 if inPort, ok := classifierInfo[InPort]; ok {
2613 nniInterfaceID, err := IntfIDFromNniPortNum(inPort.(uint32))
2614 if err != nil {
2615 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2616 }
2617 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002618 }
Esin Karaman65409d82020-03-18 10:58:18 +00002619 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302620 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002621 if e == nil && len(nniPorts) > 0 {
2622 return nniPorts[0], nil
2623 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302624 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002625}
2626
2627// AddGroup add or update the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002628func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002629 logger.Infow("add-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002630 if group == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002631 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002632 }
2633
2634 groupToOlt := openoltpb2.Group{
2635 GroupId: group.Desc.GroupId,
2636 Command: openoltpb2.Group_SET_MEMBERS,
2637 Action: f.buildGroupAction(),
2638 }
2639
Shrey Baid26912972020-04-16 21:02:31 +05302640 logger.Debugw("sending-group-to-device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05302641 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002642 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002643 return olterrors.NewErrAdapter("add-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002644 }
2645 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05302646 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002647 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002648 }
Shrey Baid26912972020-04-16 21:02:31 +05302649 logger.Infow("add-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002650 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002651}
2652
2653//buildGroupAction creates and returns a group action
2654func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2655 var actionCmd openoltpb2.ActionCmd
2656 var action openoltpb2.Action
2657 action.Cmd = &actionCmd
2658 //pop outer vlan
2659 action.Cmd.RemoveOuterTag = true
2660 return &action
2661}
2662
2663// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002664func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002665 logger.Infow("modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002666 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002667 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002668 }
2669
Andrea Campanellac63bba92020-03-10 17:01:04 +01002670 newGroup := f.buildGroup(group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002671 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302672 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002673
2674 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002675 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002676 }
2677
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002678 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002679 if groupExists {
2680 // group already exists
2681 current = f.buildGroup(group.Desc.GroupId, val.Desc.GetBuckets())
Shrey Baid26912972020-04-16 21:02:31 +05302682 logger.Debugw("modify-group--group exists",
2683 log.Fields{
2684 "group on the device": val,
2685 "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002686 } else {
2687 current = f.buildGroup(group.Desc.GroupId, nil)
2688 }
2689
Shrey Baid26912972020-04-16 21:02:31 +05302690 logger.Debugw("modify-group--comparing-current-and-new",
2691 log.Fields{
2692 "group on the device": current,
2693 "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002694 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002695 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002696 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002697 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002698
Shrey Baid26912972020-04-16 21:02:31 +05302699 logger.Infow("modify-group--differences found", log.Fields{
2700 "membersToBeAdded": membersToBeAdded,
2701 "membersToBeRemoved": membersToBeRemoved,
2702 "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002703
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002704 groupToOlt := openoltpb2.Group{
2705 GroupId: group.Desc.GroupId,
2706 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002707 var errAdd, errRemoved error
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002708 if membersToBeAdded != nil && len(membersToBeAdded) > 0 {
2709 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2710 groupToOlt.Members = membersToBeAdded
2711 //execute addMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002712 errAdd = f.callGroupAddRemove(&groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002713 }
2714 if membersToBeRemoved != nil && len(membersToBeRemoved) > 0 {
2715 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2716 groupToOlt.Members = membersToBeRemoved
2717 //execute removeMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002718 errRemoved = f.callGroupAddRemove(&groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002719 }
2720
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002721 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002722 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302723 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002724 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002725 }
Shrey Baid26912972020-04-16 21:02:31 +05302726 logger.Infow("modify-group-was-success--storing-group",
2727 log.Fields{
2728 "group": group,
2729 "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002730 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302731 logger.Warnw("one-of-the-group-add/remove-operations-failed--cannot-save-group-modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002732 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002733 if errAdd != nil {
2734 return errAdd
2735 }
2736 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002737 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002738 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002739}
2740
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002741//callGroupAddRemove performs add/remove buckets operation for the indicated group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002742func (f *OpenOltFlowMgr) callGroupAddRemove(group *openoltpb2.Group) error {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002743 if err := f.performGroupOperation(group); err != nil {
2744 st, _ := status.FromError(err)
2745 //ignore already exists error code
2746 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002747 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002748 }
2749 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002750 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002751}
2752
2753//findDiff compares group members and finds members which only exists in groups2
2754func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2755 var members []*openoltpb2.GroupMember
2756 for _, bucket := range group2.Members {
2757 if !f.contains(group1.Members, bucket) {
2758 // bucket does not exist and must be added
2759 members = append(members, bucket)
2760 }
2761 }
2762 return members
2763}
2764
2765//contains returns true if the members list contains the given member; false otherwise
2766func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2767 for _, groupMember := range members {
2768 if groupMember.InterfaceId == member.InterfaceId {
2769 return true
2770 }
2771 }
2772 return false
2773}
2774
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002775//performGroupOperation call performGroupOperation operation of openolt proto
2776func (f *OpenOltFlowMgr) performGroupOperation(group *openoltpb2.Group) error {
Shrey Baid26912972020-04-16 21:02:31 +05302777 logger.Debugw("sending-group-to-device",
2778 log.Fields{
2779 "groupToOlt": group,
2780 "command": group.Command})
Esin Karamanccb714b2019-11-29 15:02:06 +00002781 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2782 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002783 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002784 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002785 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002786}
2787
2788//buildGroup build openoltpb2.Group from given group id and bucket list
2789func (f *OpenOltFlowMgr) buildGroup(groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
2790 group := openoltpb2.Group{
2791 GroupId: groupID}
2792 // create members of the group
2793 if buckets != nil {
2794 for _, ofBucket := range buckets {
2795 member := f.buildMember(ofBucket)
2796 if member != nil && !f.contains(group.Members, member) {
2797 group.Members = append(group.Members, member)
2798 }
2799 }
2800 }
2801 return &group
2802}
2803
2804//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
2805func (f *OpenOltFlowMgr) buildMember(ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
2806 var outPort uint32
2807 outPortFound := false
2808 for _, ofAction := range ofBucket.Actions {
2809 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2810 outPort = ofAction.GetOutput().Port
2811 outPortFound = true
2812 }
2813 }
2814
2815 if !outPortFound {
Shrey Baid26912972020-04-16 21:02:31 +05302816 logger.Debugw("bucket-skipped-since-no-out-port-found-in-it", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002817 return nil
2818 }
2819 interfaceID := IntfIDFromUniPortNum(outPort)
Shrey Baid26912972020-04-16 21:02:31 +05302820 logger.Debugw("got-associated-interface-id-of-the-port",
2821 log.Fields{
2822 "portNumber:": outPort,
2823 "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002824 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2825 member := openoltpb2.GroupMember{
2826 InterfaceId: interfaceID,
2827 InterfaceType: openoltpb2.GroupMember_PON,
2828 GemPortId: groupInfo.gemPortID,
2829 Priority: groupInfo.servicePriority,
2830 }
2831 //add member to the group
2832 return &member
2833 }
Shrey Baid26912972020-04-16 21:02:31 +05302834 logger.Warnf("bucket-skipped-since-interface-2-gem-mapping-cannot-be-found", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002835 return nil
2836}
2837
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002838//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04002839func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002840
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002841 onuDev, err := f.getOnuDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302842 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302843 logger.Errorw("couldnt-find-onu-child-device",
2844 log.Fields{
2845 "intf-id": intfID,
2846 "onu-id": onuID,
2847 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002848 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302849 }
Shrey Baid26912972020-04-16 21:02:31 +05302850 logger.Debugw("got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002851
Manikkaraj kb1d51442019-07-23 10:41:02 -04002852 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002853 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Shrey Baid26912972020-04-16 21:02:31 +05302854 logger.Debugw("sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
manikkaraj k17652a72019-05-06 09:06:36 -04002855 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2856 tpDownloadMsg,
2857 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302858 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002859 onuDev.deviceType,
2860 onuDev.deviceID,
2861 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002862 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302863 return olterrors.NewErrCommunication("send-techprofile-download-request",
2864 log.Fields{
2865 "from-adapter": f.deviceHandler.device.Type,
2866 "to-adapter": onuDev.deviceType,
2867 "onu-id": onuDev.deviceID,
2868 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002869 }
Shrey Baid26912972020-04-16 21:02:31 +05302870 logger.Infow("success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302871 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302872}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002873
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302874//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002875func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302876
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002877 f.onuGemInfoLock[intfID].Lock()
2878 defer f.onuGemInfoLock[intfID].Unlock()
2879
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302880 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2881 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002882 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002883 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302884 }
Shrey Baid26912972020-04-16 21:02:31 +05302885 logger.Infow("updated-onuinfo",
2886 log.Fields{
2887 "intf-id": intfID,
2888 "onu-id": onuID,
2889 "serial-num": serialNum,
2890 "onu": onu,
2891 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002892 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002893}
2894
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302895//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302896func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002897
2898 f.onuGemInfoLock[intfID].Lock()
2899 defer f.onuGemInfoLock[intfID].Unlock()
2900
Shrey Baid26912972020-04-16 21:02:31 +05302901 logger.Infow("adding-gem-to-onu-info-map",
2902 log.Fields{
2903 "gem": gemPort,
2904 "intf": intfID,
2905 "onu": onuID,
2906 "device-id": f.deviceHandler.device.Id,
2907 "onu-gem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302908 onugem := f.onuGemInfo[intfID]
2909 // update the gem to the local cache as well as to kv strore
2910 for idx, onu := range onugem {
2911 if onu.OnuID == onuID {
2912 // check if gem already exists , else update the cache and kvstore
2913 for _, gem := range onu.GemPorts {
2914 if gem == gemPort {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002915 logger.Debugw("gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302916 log.Fields{
2917 "gem": gemPort,
2918 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302919 return
2920 }
2921 }
2922 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2923 f.onuGemInfo[intfID] = onugem
2924 }
2925 }
npujarec5762e2020-01-01 14:08:48 +05302926 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302927 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302928 logger.Errorw("failed-to-add-gem-to-onu",
2929 log.Fields{
2930 "intf-id": intfID,
2931 "onu-id": onuID,
2932 "gemPort": gemPort,
2933 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002934 return
2935 }
Shrey Baid26912972020-04-16 21:02:31 +05302936 logger.Infow("gem-added-to-onu-info-map",
2937 log.Fields{
2938 "gem": gemPort,
2939 "intf": intfID,
2940 "onu": onuID,
2941 "device-id": f.deviceHandler.device.Id,
2942 "onu-gem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002943}
2944
2945// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002946
2947//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 -07002948func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302949
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002950 f.onuGemInfoLock[intfID].Lock()
2951 defer f.onuGemInfoLock[intfID].Unlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302952
Shrey Baid26912972020-04-16 21:02:31 +05302953 logger.Infow("getting-onu-id-from-gem-port-and-pon-port",
2954 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002955 "device-id": f.deviceHandler.device.Id,
2956 "onu-geminfo": f.onuGemInfo[intfID],
2957 "intf-id": intfID,
2958 "gemport-id": gemPortID})
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002959
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302960 // get onuid from the onugem info cache
2961 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002962
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302963 for _, onu := range onugem {
2964 for _, gem := range onu.GemPorts {
2965 if gem == gemPortID {
2966 return onu.OnuID, nil
2967 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002968 }
2969 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302970 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002971 "interface-id": intfID,
2972 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00002973 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002974}
2975
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002976//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302977func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002978 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002979 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002980 var err error
2981
2982 if packetIn.IntfType == "pon" {
2983 // packet indication does not have serial number , so sending as nil
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002984 if onuID, err = f.getOnuIDfromGemPortMap(packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002985 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002986 return logicalPortNum, err
2987 }
2988 if packetIn.PortNo != 0 {
2989 logicalPortNum = packetIn.PortNo
2990 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002991 uniID := uint32(0) // FIXME - multi-uni support
2992 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002993 }
2994 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
npujarec5762e2020-01-01 14:08:48 +05302995 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002996 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002997 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002998 }
Shrey Baid26912972020-04-16 21:02:31 +05302999 logger.Infow("retrieved-logicalport-from-packet-in",
3000 log.Fields{
3001 "logical-port-num": logicalPortNum,
3002 "intf-type": packetIn.IntfType,
3003 "packet": hex.EncodeToString(packetIn.Pkt),
3004 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003005 return logicalPortNum, nil
3006}
3007
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003008//GetPacketOutGemPortID returns gemPortId
npujarec5762e2020-01-01 14:08:48 +05303009func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003010 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003011 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303012
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003013 f.onuGemInfoLock[intfID].Lock()
3014 defer f.onuGemInfoLock[intfID].Unlock()
3015
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303016 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
3017
3018 gemPortID, ok := f.packetInGemPort[pktInkey]
3019 if ok {
Shrey Baid26912972020-04-16 21:02:31 +05303020 logger.Debugw("found-gemport-for-pktin-key",
3021 log.Fields{
3022 "pktinkey": pktInkey,
3023 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303024 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003025 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303026 //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 +05303027 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303028 if err == nil {
3029 if gemPortID != 0 {
3030 f.packetInGemPort[pktInkey] = gemPortID
Shrey Baid26912972020-04-16 21:02:31 +05303031 logger.Infow("found-gem-port-from-kv-store-and-updating-cache-with-gemport",
3032 log.Fields{
3033 "pktinkey": pktInkey,
3034 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303035 return gemPortID, nil
3036 }
3037 }
Shrey Baid26912972020-04-16 21:02:31 +05303038 return uint32(0), olterrors.NewErrNotFound("gem-port",
3039 log.Fields{
3040 "pktinkey": pktInkey,
3041 "gem": gemPortID}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003042}
3043
npujarec5762e2020-01-01 14:08:48 +05303044func installFlowOnAllGemports(ctx context.Context,
3045 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003046 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003047 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05303048 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303049 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303050 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003051 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003052 args map[string]uint32,
3053 classifier map[string]interface{}, action map[string]interface{},
3054 logicalFlow *ofp.OfpFlowStats,
3055 gemPorts []uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303056 TpInst *tp.TechProfile,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003057 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00003058 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003059 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003060 vlanID ...uint32) {
Shrey Baid26912972020-04-16 21:02:31 +05303061 logger.Debugw("installing-flow-on-all-gem-ports",
3062 log.Fields{
3063 "FlowType": FlowType,
3064 "gemPorts": gemPorts,
3065 "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05303066
Gamze Abaka724d0852020-03-18 12:10:24 +00003067 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
3068 // We need to trim prefix "0b", before further processing
3069 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
3070 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
3071
3072 // If a particular character in the string is set to '1', identify the index of this character from
3073 // the LSB position which marks the PCP bit consumed by the given gem port.
3074 // This PCP bit now becomes a classifier in the flow.
3075
3076 attributes := TpInst.DownstreamGemPortAttributeList
3077 if direction == Upstream {
3078 attributes = TpInst.UpstreamGemPortAttributeList
3079 }
3080
3081 for _, gemPortAttribute := range attributes {
3082 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
3083 continue
3084 }
3085 gemPortID := gemPortAttribute.GemportID
3086 if allPbitsMarked(gemPortAttribute.PbitMap) {
3087 classifier[VlanPcp] = uint32(VlanPCPMask)
3088 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003089 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003090 } else if FlowType == EapolFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003091 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 +00003092 }
3093 } else {
3094 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
3095 if pbitSet == BinaryBit1 {
3096 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3097 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003098 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003099 } else if FlowType == EapolFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003100 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 +00003101 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05303102 }
3103 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04003104 }
3105 }
3106}
3107
Gamze Abaka724d0852020-03-18 12:10:24 +00003108func allPbitsMarked(pbitMap string) bool {
3109 for pos, pBit := range pbitMap {
3110 if pos >= 2 && pBit != BinaryBit1 {
3111 return false
3112 }
3113 }
3114 return true
3115}
3116
David K. Bainbridge794735f2020-02-11 21:01:37 -08003117func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05303118 logger.Debug("adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003119 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003120 classifier[PacketTagType] = DoubleTag
3121 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003122 /* We manage flowId resource pool on per PON port basis.
3123 Since this situation is tricky, as a hack, we pass the NNI port
3124 index (network_intf_id) as PON port Index for the flowId resource
3125 pool. Also, there is no ONU Id available for trapping DHCP packets
3126 on NNI port, use onu_id as -1 (invalid)
3127 ****************** CAVEAT *******************
3128 This logic works if the NNI Port Id falls within the same valid
3129 range of PON Port Ids. If this doesn't work for some OLT Vendor
3130 we need to have a re-look at this.
3131 *********************************************
3132 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003133 onuID := -1
3134 uniID := -1
3135 gemPortID := -1
3136 allocID := -1
David K. Bainbridge794735f2020-02-11 21:01:37 -08003137 networkInterfaceID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303138 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303139 return olterrors.NewErrNotFound("nni-intreface-id",
3140 log.Fields{
3141 "classifier": classifier,
3142 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003143 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303144 }
3145
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003146 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303147 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05303148 logger.Info("flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003149 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003150 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003151 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003152 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303153 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id",
3154 log.Fields{
3155 "interface-id": networkInterfaceID,
3156 "onu-id": onuID,
3157 "uni-id": uniID,
3158 "gem-port-id": gemPortID,
3159 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003160 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003161 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003162 classifierProto, err := makeOpenOltClassifierField(classifier)
3163 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003164 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003165 }
Shrey Baid26912972020-04-16 21:02:31 +05303166 logger.Debugw("created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003167 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003168 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003169 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003170 }
Shrey Baid26912972020-04-16 21:02:31 +05303171 logger.Debugw("created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003172 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3173 OnuId: int32(onuID), // OnuId not required
3174 UniId: int32(uniID), // UniId not used
3175 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07003176 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003177 AllocId: int32(allocID), // AllocId not used
3178 NetworkIntfId: int32(networkInterfaceID),
3179 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003180 Classifier: classifierProto,
3181 Action: actionProto,
3182 Priority: int32(logicalFlow.Priority),
3183 Cookie: logicalFlow.Cookie,
3184 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003185 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003186 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003187 }
Shrey Baid26912972020-04-16 21:02:31 +05303188 logger.Info("dhcp-trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003189 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3190 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3191 int32(onuID),
3192 int32(uniID),
3193 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003194 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003195 }
3196 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003197}
salmansiddiqui7ac62132019-08-22 03:58:50 +00003198
Esin Karamanae41e2b2019-12-17 18:13:13 +00003199//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
3200func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
3201 var packetType string
3202 ovid, ivid := false, false
3203 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
3204 vid := vlanID & VlanvIDMask
3205 if vid != ReservedVlan {
3206 ovid = true
3207 }
3208 }
3209 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
3210 vid := uint32(metadata)
3211 if vid != ReservedVlan {
3212 ivid = true
3213 }
3214 }
3215 if ovid && ivid {
3216 packetType = DoubleTag
3217 } else if !ovid && !ivid {
3218 packetType = Untagged
3219 } else {
3220 packetType = SingleTag
3221 }
3222 return packetType
3223}
3224
3225//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08003226func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Shrey Baid26912972020-04-16 21:02:31 +05303227 logger.Infow("adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003228 action := make(map[string]interface{})
3229 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
3230 action[TrapToHost] = true
3231 /* We manage flowId resource pool on per PON port basis.
3232 Since this situation is tricky, as a hack, we pass the NNI port
3233 index (network_intf_id) as PON port Index for the flowId resource
3234 pool. Also, there is no ONU Id available for trapping packets
3235 on NNI port, use onu_id as -1 (invalid)
3236 ****************** CAVEAT *******************
3237 This logic works if the NNI Port Id falls within the same valid
3238 range of PON Port Ids. If this doesn't work for some OLT Vendor
3239 we need to have a re-look at this.
3240 *********************************************
3241 */
3242 onuID := -1
3243 uniID := -1
3244 gemPortID := -1
3245 allocID := -1
3246 networkInterfaceID, err := getNniIntfID(classifier, action)
3247 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303248 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003249 "classifier": classifier,
3250 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003251 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003252 }
3253 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303254 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Shrey Baid26912972020-04-16 21:02:31 +05303255 logger.Info("igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003256 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003257 }
npujarec5762e2020-01-01 14:08:48 +05303258 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003259 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303260 return olterrors.NewErrNotFound("igmp-flow-id",
3261 log.Fields{
3262 "interface-id": networkInterfaceID,
3263 "onu-id": onuID,
3264 "uni-id": uniID,
3265 "gem-port-id": gemPortID,
3266 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003267 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003268 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003269 classifierProto, err := makeOpenOltClassifierField(classifier)
3270 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003271 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003272 }
Shrey Baid26912972020-04-16 21:02:31 +05303273 logger.Debugw("created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003274 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003275 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003276 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003277 }
Shrey Baid26912972020-04-16 21:02:31 +05303278 logger.Debugw("created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003279 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3280 OnuId: int32(onuID), // OnuId not required
3281 UniId: int32(uniID), // UniId not used
3282 FlowId: flowID,
3283 FlowType: Downstream,
3284 AllocId: int32(allocID), // AllocId not used
3285 NetworkIntfId: int32(networkInterfaceID),
3286 GemportId: int32(gemPortID), // GemportId not used
3287 Classifier: classifierProto,
3288 Action: actionProto,
3289 Priority: int32(logicalFlow.Priority),
3290 Cookie: logicalFlow.Cookie,
3291 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003292 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003293 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003294 }
Shrey Baid26912972020-04-16 21:02:31 +05303295 logger.Info("igmp-trap-on-nni-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003296 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3297 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3298 int32(onuID),
3299 int32(uniID),
3300 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003301 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003302 }
3303 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003304}
3305
salmansiddiqui7ac62132019-08-22 03:58:50 +00003306func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
3307 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05303308 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003309 }
3310 if Dir == tp_pb.Direction_UPSTREAM {
3311 return "upstream", nil
3312 } else if Dir == tp_pb.Direction_DOWNSTREAM {
3313 return "downstream", nil
3314 }
3315 return "", nil
3316}
3317
npujarec5762e2020-01-01 14:08:48 +05303318func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00003319 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003320 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00003321 var gemPort uint32
3322 intfID := args[IntfID]
3323 onuID := args[OnuID]
3324 uniID := args[UniID]
3325 portNo := args[PortNo]
3326 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00003327 if ipProto, ok := classifierInfo[IPProto]; ok {
3328 if ipProto.(uint32) == IPProtoDhcp {
Shrey Baid26912972020-04-16 21:02:31 +05303329 logger.Info("adding-dhcp-flow")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003330 if pcp, ok := classifierInfo[VlanPcp]; ok {
3331 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3332 tp_pb.Direction_UPSTREAM,
3333 pcp.(uint32))
3334 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00003335
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003336 f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003337 } else {
3338 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003339 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003340 }
3341
Girish Gowdra32625212020-04-29 11:26:35 -07003342 } else if ipProto.(uint32) == IgmpProto {
Shrey Baid26912972020-04-16 21:02:31 +05303343 logger.Infow("adding-us-igmp-flow",
3344 log.Fields{
3345 "intf-id": intfID,
3346 "onu-id": onuID,
3347 "uni-id": uniID,
3348 "classifier-info:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003349 if pcp, ok := classifierInfo[VlanPcp]; ok {
3350 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3351 tp_pb.Direction_UPSTREAM,
3352 pcp.(uint32))
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003353 f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003354 } else {
3355 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003356 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003357 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003358 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303359 logger.Errorw("invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003360 return
3361 }
3362 } else if ethType, ok := classifierInfo[EthType]; ok {
3363 if ethType.(uint32) == EapEthType {
Shrey Baid26912972020-04-16 21:02:31 +05303364 logger.Info("adding-eapol-flow")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003365 var vlanID uint32
3366 if val, ok := classifierInfo[VlanVid]; ok {
3367 vlanID = (val.(uint32)) & VlanvIDMask
3368 } else {
3369 vlanID = DefaultMgmtVlan
3370 }
3371 if pcp, ok := classifierInfo[VlanPcp]; ok {
3372 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3373 tp_pb.Direction_UPSTREAM,
3374 pcp.(uint32))
3375
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003376 f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003377 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003378 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003379 }
3380 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003381 } else if _, ok := actionInfo[PushVlan]; ok {
Shrey Baid26912972020-04-16 21:02:31 +05303382 logger.Info("adding-upstream-data-rule")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003383 if pcp, ok := classifierInfo[VlanPcp]; ok {
3384 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
3385 tp_pb.Direction_UPSTREAM,
3386 pcp.(uint32))
3387 //Adding HSIA upstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003388 f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003389 } else {
3390 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003391 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003392 }
3393 } else if _, ok := actionInfo[PopVlan]; ok {
Shrey Baid26912972020-04-16 21:02:31 +05303394 logger.Info("adding-downstream-data-rule")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003395 if pcp, ok := classifierInfo[VlanPcp]; ok {
3396 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05003397 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003398 pcp.(uint32))
3399 //Adding HSIA downstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003400 f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003401 } else {
3402 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003403 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003404 }
3405 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303406 logger.Errorw("invalid-flow-type-to-handle",
3407 log.Fields{
3408 "classifier": classifierInfo,
3409 "action": actionInfo,
3410 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003411 return
3412 }
3413 // Send Techprofile download event to child device in go routine as it takes time
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003414 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003415}
3416
Gamze Abakafee36392019-10-03 11:17:24 +00003417func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
3418 flowIDList := f.flowsUsedByGemPort[gemPK]
3419 if len(flowIDList) > 1 {
3420 return true
3421 }
3422 return false
3423}
3424
npujarec5762e2020-01-01 14:08:48 +05303425func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3426 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003427 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3428 for _, currentGemPort := range currentGemPorts {
3429 for _, tpGemPort := range tpGemPorts {
3430 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3431 return true, currentGemPort
3432 }
3433 }
3434 }
Girish Gowdra54934262019-11-13 14:19:55 +05303435 if tpInst.InstanceCtrl.Onu == "single-instance" {
3436 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
npujarec5762e2020-01-01 14:08:48 +05303437 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID)
3438 f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID)
Girish Gowdra54934262019-11-13 14:19:55 +05303439
3440 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3441 // still be used on other uni ports.
3442 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3443 // on any other uni port.
npujarec5762e2020-01-01 14:08:48 +05303444 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID)
Shrey Baid26912972020-04-16 21:02:31 +05303445 logger.Debugw("got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303446 for i := 0; i < len(tpInstances); i++ {
3447 tpI := tpInstances[i]
3448 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303449 for _, tpGemPort := range tpGemPorts {
3450 if tpGemPort.GemportID != gemPortID {
Shrey Baid26912972020-04-16 21:02:31 +05303451 logger.Debugw("single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303452 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303453 }
3454 }
3455 }
3456 }
Shrey Baid26912972020-04-16 21:02:31 +05303457 logger.Debug("tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003458 return false, 0
3459}
3460
salmansiddiqui7ac62132019-08-22 03:58:50 +00003461func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003462 for _, field := range flows.GetOfbFields(flow) {
3463 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003464 classifierInfo[EthType] = field.GetEthType()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003465 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003466 } else if field.Type == flows.ETH_DST {
3467 classifierInfo[EthDst] = field.GetEthDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003468 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003469 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003470 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003471 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003472 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003473 classifierInfo[InPort] = field.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003474 logger.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003475 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303476 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00003477 logger.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003478 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003479 classifierInfo[VlanPcp] = field.GetVlanPcp()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003480 logger.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003481 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003482 classifierInfo[UDPDst] = field.GetUdpDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003483 logger.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003484 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003485 classifierInfo[UDPSrc] = field.GetUdpSrc()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003486 logger.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003487 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003488 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003489 logger.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003490 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003491 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003492 logger.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003493 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003494 classifierInfo[Metadata] = field.GetTableMetadata()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003495 logger.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003496 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003497 classifierInfo[TunnelID] = field.GetTunnelId()
Girish Kumar2ad402b2020-03-20 19:45:12 +00003498 logger.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003499 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303500 logger.Errorw("un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003501 return
3502 }
3503 }
3504}
3505
3506func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003507 for _, action := range flows.GetActions(flow) {
3508 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003509 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003510 actionInfo[Output] = out.GetPort()
Shrey Baid26912972020-04-16 21:02:31 +05303511 logger.Debugw("action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003512 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003513 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003514 }
Scott Baker355d1742019-10-24 10:57:52 -07003515 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003516 actionInfo[PopVlan] = true
Girish Kumar2ad402b2020-03-20 19:45:12 +00003517 logger.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003518 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003519 if out := action.GetPush(); out != nil {
3520 if tpid := out.GetEthertype(); tpid != 0x8100 {
Shrey Baid26912972020-04-16 21:02:31 +05303521 logger.Errorw("invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003522 } else {
3523 actionInfo[PushVlan] = true
3524 actionInfo[TPID] = tpid
Girish Kumar2ad402b2020-03-20 19:45:12 +00003525 logger.Debugw("action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303526 log.Fields{
3527 "push-tpid": actionInfo[TPID].(uint32),
3528 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003529 }
3530 }
Scott Baker355d1742019-10-24 10:57:52 -07003531 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003532 if out := action.GetSetField(); out != nil {
3533 if field := out.GetField(); field != nil {
3534 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003535 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003536 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00003537 /*logger.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
Esin Karamanccb714b2019-11-29 15:02:06 +00003538 formulateSetFieldActionInfoFromFlow(field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003539 }
3540 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003541 } else if action.Type == flows.GROUP {
3542 formulateGroupActionInfoFromFlow(action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003543 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003544 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003545 }
3546 }
3547 return nil
3548}
3549
Esin Karamanccb714b2019-11-29 15:02:06 +00003550func formulateSetFieldActionInfoFromFlow(field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
3551 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003552 fieldtype := ofbField.GetType()
3553 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003554 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3555 actionInfo[VlanVid] = vlan & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00003556 logger.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003557 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303558 logger.Error("no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003559 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003560 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3561 pcp := ofbField.GetVlanPcp()
3562 actionInfo[VlanPcp] = pcp
3563 log.Debugw("action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003564 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003565 logger.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003566 }
3567 }
3568}
3569
3570func formulateGroupActionInfoFromFlow(action *ofp.OfpAction, actionInfo map[string]interface{}) {
3571 if action.GetGroup() == nil {
Shrey Baid26912972020-04-16 21:02:31 +05303572 logger.Warn("no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003573 } else {
3574 actionInfo[GroupID] = action.GetGroup().GroupId
Girish Kumar2ad402b2020-03-20 19:45:12 +00003575 logger.Debugw("action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003576 }
3577}
3578
salmansiddiqui7ac62132019-08-22 03:58:50 +00003579func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003580 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Shrey Baid26912972020-04-16 21:02:31 +05303581 logger.Debug("controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003582 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3583 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003584 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003585 classifierInfo[InPort] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303586 logger.Debugw("upstream-pon-to-controller-flow--inport-in-tunnelid",
3587 log.Fields{
3588 "newinport": classifierInfo[InPort].(uint32),
3589 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003590 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303591 return olterrors.NewErrNotFound("child-in-port",
3592 log.Fields{
3593 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3594 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003595 }
3596 }
3597 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303598 logger.Debug("non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003599 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003600 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003601 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003602 actionInfo[Output] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303603 logger.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid",
3604 log.Fields{
3605 "newoutport": actionInfo[Output].(uint32),
3606 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003607 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303608 return olterrors.NewErrNotFound("out-port",
3609 log.Fields{
3610 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3611 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003612 }
3613 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3614 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003615 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003616 classifierInfo[InPort] = uniPort
Shrey Baid26912972020-04-16 21:02:31 +05303617 logger.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid",
3618 log.Fields{
3619 "newinport": actionInfo[Output].(uint32),
3620 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003621 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303622 return olterrors.NewErrNotFound("nni-port",
3623 log.Fields{
3624 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3625 "in-port": classifierInfo[InPort].(uint32),
3626 "out-port": actionInfo[Output].(uint32),
3627 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003628 }
3629 }
3630 }
3631 return nil
3632}
Gamze Abakafee36392019-10-03 11:17:24 +00003633
Chaitrashree G S90a17952019-11-14 21:51:21 -05003634func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003635 /* Metadata 8 bytes:
3636 Most Significant 2 Bytes = Inner VLAN
3637 Next 2 Bytes = Tech Profile ID(TPID)
3638 Least Significant 4 Bytes = Port ID
3639 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3640 subscriber related flows.
3641 */
3642 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
3643 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003644 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003645 }
3646 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003647 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003648}
3649
3650func appendUnique(slice []uint32, item uint32) []uint32 {
3651 for _, sliceElement := range slice {
3652 if sliceElement == item {
3653 return slice
3654 }
3655 }
3656 return append(slice, item)
3657}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303658
3659// getNniIntfID gets nni intf id from the flow classifier/action
3660func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
3661
3662 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3663 if portType == voltha.Port_PON_OLT {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003664 intfID, err := IntfIDFromNniPortNum(action[Output].(uint32))
3665 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003666 logger.Debugw("invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003667 log.Fields{
3668 "port-number": action[Output].(uint32),
3669 "error": err})
3670 return uint32(0), err
3671 }
Shrey Baid26912972020-04-16 21:02:31 +05303672 logger.Infow("output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303673 return intfID, nil
3674 } else if portType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003675 intfID, err := IntfIDFromNniPortNum(classifier[InPort].(uint32))
3676 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003677 logger.Debugw("invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003678 log.Fields{
3679 "port-number": action[Output].(uint32),
3680 "error": err})
3681 return uint32(0), err
3682 }
Shrey Baid26912972020-04-16 21:02:31 +05303683 logger.Infow("input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303684 return intfID, nil
3685 }
3686 return uint32(0), nil
3687}
3688
3689// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
npujarec5762e2020-01-01 14:08:48 +05303690func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303691 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
3692
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003693 f.onuGemInfoLock[intfID].Lock()
3694 defer f.onuGemInfoLock[intfID].Unlock()
3695
Matt Jeanneret1719a072019-12-20 14:50:14 -05003696 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303697 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003698 if lookupGemPort == gemPort {
Shrey Baid26912972020-04-16 21:02:31 +05303699 logger.Infow("pktin-key/value-found-in-cache--no-need-to-update-kv--assume-both-in-sync",
3700 log.Fields{
3701 "pktinkey": pktInkey,
3702 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003703 return
3704 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303705 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003706 f.packetInGemPort[pktInkey] = gemPort
3707
npujarec5762e2020-01-01 14:08:48 +05303708 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Shrey Baid26912972020-04-16 21:02:31 +05303709 logger.Infow("pktin-key-not-found-in-local-cache-value-is-different--updating-cache-and-kv-store",
3710 log.Fields{
3711 "pktinkey": pktInkey,
3712 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303713 return
3714}
3715
3716// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303717func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003718
3719 f.onuGemInfoLock[intfID].Lock()
3720 defer f.onuGemInfoLock[intfID].Unlock()
3721
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303722 onugem := f.onuGemInfo[intfID]
3723 for idx, onu := range onugem {
3724 if onu.OnuID == onuID {
3725 for _, uni := range onu.UniPorts {
3726 if uni == portNum {
Shrey Baid26912972020-04-16 21:02:31 +05303727 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 +05303728 return
3729 }
3730 }
3731 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3732 f.onuGemInfo[intfID] = onugem
3733 }
3734 }
npujarec5762e2020-01-01 14:08:48 +05303735 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303736}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303737
npujarec5762e2020-01-01 14:08:48 +05303738func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3739 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303740 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303741 logger.Error("failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303742 return
3743 }
3744 for gem, FlowIDs := range flowIDsList {
3745 gemPK := gemPortKey{intf, uint32(gem)}
3746 f.flowsUsedByGemPort[gemPK] = FlowIDs
3747 }
3748 return
3749}
Esin Karamanccb714b2019-11-29 15:02:06 +00003750
3751//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
3752//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05303753func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
3754 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00003755 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303756 logger.Error("failed-to-get-pon-interface-to-multicast-queue-map")
Esin Karamanccb714b2019-11-29 15:02:06 +00003757 return
3758 }
3759 for intf, queueInfo := range storedMulticastQueueMap {
3760 q := queueInfoBrief{
3761 gemPortID: queueInfo[0],
3762 servicePriority: queueInfo[1],
3763 }
3764 f.interfaceToMcastQueueMap[intf] = &q
3765 }
3766}
3767
3768//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
3769//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
3770//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05303771func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
3772 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00003773 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003774 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00003775 }
3776 if exists {
3777 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
3778 }
3779 return nil, exists, nil
3780}
3781
3782func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
3783 groupDesc := ofp.OfpGroupDesc{
3784 Type: ofp.OfpGroupType_OFPGT_ALL,
3785 GroupId: groupID,
3786 }
3787 groupEntry := ofp.OfpGroupEntry{
3788 Desc: &groupDesc,
3789 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003790 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003791 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00003792 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003793 bucket := ofp.OfpBucket{
3794 Actions: acts,
3795 }
3796 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00003797 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003798 return &groupEntry
3799}