blob: 6ad1b60f865a96d4c85dcc0d2d59b6f5890b17c1 [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
22 "crypto/md5"
Matteo Scandolo6056e822019-11-13 14:05:29 -080023 "encoding/hex"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "encoding/json"
Girish Gowdracefae192020-03-19 18:14:10 -070025 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053026 "fmt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040027 "math/big"
Girish Gowdrafae935c2020-02-17 19:21:44 +053028 "strings"
William Kurkian740a09c2019-10-23 17:07:38 -040029 "sync"
Girish Gowdra3d633032019-12-10 16:37:05 +053030 "time"
Manikkaraj kb1d51442019-07-23 10:41:02 -040031
Esin Karamanccb714b2019-11-29 15:02:06 +000032 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v3/pkg/log"
34 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080035 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000036 "github.com/opencord/voltha-protos/v3/go/common"
37 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
38 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
39 openoltpb2 "github.com/opencord/voltha-protos/v3/go/openolt"
40 tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
41 "github.com/opencord/voltha-protos/v3/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040042
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040043 //deepcopy "github.com/getlantern/deepcopy"
Girish Gowdra3d633032019-12-10 16:37:05 +053044 "github.com/EagleChen/mapmutex"
Thomas Lee S94109f12020-03-03 16:39:29 +053045 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000046 "google.golang.org/grpc/codes"
47 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053048)
49
50const (
51 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070053 //HsiaFlow flow category
54 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053055
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070056 //EapolFlow flow category
57 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053058
Manikkaraj kb1d51442019-07-23 10:41:02 -040059 //DhcpFlow flow category
60 DhcpFlow = "DHCP_FLOW"
61
Esin Karamanccb714b2019-11-29 15:02:06 +000062 //MulticastFlow flow category
63 MulticastFlow = "MULTICAST_FLOW"
64
Esin Karamanae41e2b2019-12-17 18:13:13 +000065 //IgmpFlow flow category
66 IgmpFlow = "IGMP_FLOW"
67
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068 //IPProtoDhcp flow category
69 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053070
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070071 //IPProtoIgmp flow category
72 IPProtoIgmp = 2
73
74 //EapEthType eapethtype value
75 EapEthType = 0x888e
76 //LldpEthType lldp ethtype value
77 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000078 //IPv4EthType IPv4 ethernet type value
79 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070080
81 //IgmpProto proto value
82 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053083
Andrea Campanella7acc0b92020-02-14 09:20:49 +010084 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
85 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040086
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087 //DefaultMgmtVlan default vlan value
88 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053089
manikkaraj kbf256be2019-03-25 00:13:48 +053090 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070091
David K. Bainbridge82efc492019-09-04 09:57:11 -070092 //Upstream constant
93 Upstream = "upstream"
94 //Downstream constant
95 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000096 //Multicast constant
97 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070098 //PacketTagType constant
99 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700100 //Untagged constant
101 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700102 //SingleTag constant
103 SingleTag = "single_tag"
104 //DoubleTag constant
105 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +0530106
107 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108
109 //EthType constant
110 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +0000111 //EthDst constant
112 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113 //TPID constant
114 TPID = "tpid"
115 //IPProto constant
116 IPProto = "ip_proto"
117 //InPort constant
118 InPort = "in_port"
119 //VlanVid constant
120 VlanVid = "vlan_vid"
121 //VlanPcp constant
122 VlanPcp = "vlan_pcp"
123
124 //UDPDst constant
125 UDPDst = "udp_dst"
126 //UDPSrc constant
127 UDPSrc = "udp_src"
128 //Ipv4Dst constant
129 Ipv4Dst = "ipv4_dst"
130 //Ipv4Src constant
131 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700132 //Metadata constant
133 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700134 //TunnelID constant
135 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700136 //Output constant
137 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000138 //GroupID constant
139 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700140 // Actions
141
142 //PopVlan constant
143 PopVlan = "pop_vlan"
144 //PushVlan constant
145 PushVlan = "push_vlan"
146 //TrapToHost constant
147 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400148 //MaxMeterBand constant
149 MaxMeterBand = 2
150 //VlanPCPMask contant
151 VlanPCPMask = 0xFF
152 //VlanvIDMask constant
153 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000154 //IntfID constant
155 IntfID = "intfId"
156 //OnuID constant
157 OnuID = "onuId"
158 //UniID constant
159 UniID = "uniId"
160 //PortNo constant
161 PortNo = "portNo"
162 //AllocID constant
163 AllocID = "allocId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000164
165 //NoneOnuID constant
166 NoneOnuID = -1
167 //NoneUniID constant
168 NoneUniID = -1
169 //NoneGemPortID constant
170 NoneGemPortID = -1
Girish Gowdrafae935c2020-02-17 19:21:44 +0530171
172 // BinaryStringPrefix is binary string prefix
173 BinaryStringPrefix = "0b"
174 // BinaryBit1 is binary bit 1 expressed as a character
175 BinaryBit1 = '1'
manikkaraj kbf256be2019-03-25 00:13:48 +0530176)
177
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400178type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700179 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400180 gemPort uint32
181}
182
Girish Gowdra3d633032019-12-10 16:37:05 +0530183type pendingFlowDeleteKey struct {
184 intfID uint32
185 onuID uint32
186 uniID uint32
187}
188
189type tpLockKey struct {
190 intfID uint32
191 onuID uint32
192 uniID uint32
193}
194
Gamze Abakafee36392019-10-03 11:17:24 +0000195type schedQueue struct {
196 direction tp_pb.Direction
197 intfID uint32
198 onuID uint32
199 uniID uint32
200 tpID uint32
201 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700202 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000203 meterID uint32
204 flowMetadata *voltha.FlowMetadata
205}
206
Esin Karamanccb714b2019-11-29 15:02:06 +0000207type queueInfoBrief struct {
208 gemPortID uint32
209 servicePriority uint32
210}
211
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700212//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530213type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000214 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000215 deviceHandler *DeviceHandler
216 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000217 onuIdsLock sync.RWMutex
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530218 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
219 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700220 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700221 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache, indexed by IntfId
222 // We need to have a global lock on the onuGemInfo map
223 onuGemInfoLock sync.RWMutex
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700224 pendingFlowDelete sync.Map
Girish Gowdra3d633032019-12-10 16:37:05 +0530225 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Esin Karamanccb714b2019-11-29 15:02:06 +0000226 perUserFlowHandleLock *mapmutex.Mutex
227 interfaceToMcastQueueMap map[uint32]*queueInfoBrief /*pon interface -> multicast queue map. Required to assign GEM to a bucket during group population*/
manikkaraj kbf256be2019-03-25 00:13:48 +0530228}
229
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700230//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
npujarec5762e2020-01-01 14:08:48 +0530231func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000232 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530233 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530234 var err error
235 var idx uint32
236
manikkaraj kbf256be2019-03-25 00:13:48 +0530237 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530238 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000239 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000240 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
241 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530242 return nil
243 }
William Kurkian740a09c2019-10-23 17:07:38 -0400244 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530245 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
246 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530247 ponPorts := rMgr.DevInfo.GetPonPorts()
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700248 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo, ponPorts)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530249 //Load the onugem info cache from kv store on flowmanager start
250 for idx = 0; idx < ponPorts; idx++ {
npujarec5762e2020-01-01 14:08:48 +0530251 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000252 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530253 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530254 //Load flowID list per gem map per interface from the kvstore.
npujarec5762e2020-01-01 14:08:48 +0530255 flowMgr.loadFlowIDlistForGem(ctx, idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530256 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700257 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdra3d633032019-12-10 16:37:05 +0530258 flowMgr.pendingFlowDelete = sync.Map{}
Girish Gowdrab77ded92020-04-08 11:45:05 -0700259 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(300, 100000000, 10000000, 1.1, 0.2)
Esin Karamanccb714b2019-11-29 15:02:06 +0000260 flowMgr.interfaceToMcastQueueMap = make(map[uint32]*queueInfoBrief)
261 //load interface to multicast queue map from kv store
npujarec5762e2020-01-01 14:08:48 +0530262 flowMgr.loadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000263 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530264 return &flowMgr
265}
266
Kent Hagermane6ff1012020-07-14 15:07:53 -0400267func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000268 logger.Debugw(ctx, "registering-flow-for-device ",
Shrey Baid26912972020-04-16 21:02:31 +0530269 log.Fields{
270 "flow": flowFromCore,
271 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000272 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
273 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
274 if !ok {
275 flowIDList = []uint32{deviceFlow.FlowId}
276 }
277 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
278 f.flowsUsedByGemPort[gemPK] = flowIDList
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530279 // update the flowids for a gem to the KVstore
Kent Hagermane6ff1012020-07-14 15:07:53 -0400280 return f.resourceMgr.UpdateFlowIDsForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400281}
282
npujarec5762e2020-01-01 14:08:48 +0530283func (f *OpenOltFlowMgr) divideAndAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000284 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
285 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000286 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530287 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700288 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530289
Neha Sharma96b7bf22020-06-15 10:37:32 +0000290 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530291 "device-id": f.deviceHandler.device.Id,
292 "intf-id": intfID,
293 "onu-id": onuID,
294 "uni-id": uniID,
295 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700296 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530297 "action": actionInfo,
298 "usmeter-iD": UsMeterID,
299 "dsmeter-iD": DsMeterID,
300 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400301 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
302 // is because the flow is an NNI flow and there would be no onu resources associated with it
303 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400304 if onuID == 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000305 logger.Errorw(ctx, "no-onu-id-for-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530306 log.Fields{
307 "port-no": portNo,
308 "classifer": classifierInfo,
309 "action": actionInfo,
310 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530311 return
312 }
313
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700314 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000315 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530316 "uni": uni,
317 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530318
319 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
320 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000321 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530322 "device-id": f.deviceHandler.device.Id,
323 "intf-id": intfID,
324 "onu-id": onuID,
325 "uni-id": uniID,
326 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700327 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530328 "action": actionInfo,
329 "usmeter-id": UsMeterID,
330 "dsmeter-id": DsMeterID,
331 "tp-id": TpID})
npujarec5762e2020-01-01 14:08:48 +0530332 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530333 if allocID == 0 || gemPorts == nil || TpInst == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000334 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530335 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
336 return
337 }
338 args := make(map[string]uint32)
339 args[IntfID] = intfID
340 args[OnuID] = onuID
341 args[UniID] = uniID
342 args[PortNo] = portNo
343 args[AllocID] = allocID
344
345 /* Flows can be added specific to gemport if p-bits are received.
346 * If no pbit mentioned then adding flows for all gemports
347 */
npujarec5762e2020-01-01 14:08:48 +0530348 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530349 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
350 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000351 logger.Errorw(ctx, "failed-to-acquire-per-user-flow-handle-lock",
Shrey Baid26912972020-04-16 21:02:31 +0530352 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700353 "intf-id": intfID,
354 "onu-id": onuID,
355 "uni-id": uniID,
356 "flow-id": flow.Id,
357 "flow-cookie": flow.Cookie,
358 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400359 return
360 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530361}
362
salmansiddiqui7ac62132019-08-22 03:58:50 +0000363// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530364func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400365
Neha Sharma96b7bf22020-06-15 10:37:32 +0000366 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530367 log.Fields{"dir": sq.direction,
368 "intf-id": sq.intfID,
369 "onu-id": sq.onuID,
370 "uni-id": sq.uniID,
371 "tp-id": sq.tpID,
372 "meter-id": sq.meterID,
373 "tp-inst": sq.tpInst,
374 "flowmetadata": sq.flowMetadata,
375 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400376
Gamze Abakafee36392019-10-03 11:17:24 +0000377 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000378 if err != nil {
379 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400380 }
381
382 /* Lets make a simple assumption that if the meter-id is present on the KV store,
383 * then the scheduler and queues configuration is applied on the OLT device
384 * in the given direction.
385 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000386
Manikkaraj kb1d51442019-07-23 10:41:02 -0400387 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530388 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400389 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530390 return olterrors.NewErrNotFound("meter",
391 log.Fields{"intf-id": sq.intfID,
392 "onu-id": sq.onuID,
393 "uni-id": sq.uniID,
394 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400395 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000396
Manikkaraj kb1d51442019-07-23 10:41:02 -0400397 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000398 if KvStoreMeter.MeterId == sq.meterID {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000399 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400400 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530402 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800403 "unsupported": "meter-id",
404 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530405 "meter-id-in-flow": sq.meterID,
406 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400407 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000408
Neha Sharma96b7bf22020-06-15 10:37:32 +0000409 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530410 log.Fields{
411 "meter-id": sq.meterID,
412 "direction": Direction,
413 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000414
Gamze Abakafee36392019-10-03 11:17:24 +0000415 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000416 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000417 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000418 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400419 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000420
421 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530422 return olterrors.NewErrNotFound("scheduler-config",
423 log.Fields{
424 "intf-id": sq.intfID,
425 "direction": sq.direction,
426 "tp-inst": sq.tpInst,
427 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000428 }
429
Manikkaraj kb1d51442019-07-23 10:41:02 -0400430 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000431 if sq.flowMetadata != nil {
432 for _, meter := range sq.flowMetadata.Meters {
433 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400434 meterConfig = meter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000435 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Shrey Baid26912972020-04-16 21:02:31 +0530436 log.Fields{"meterConfig": meterConfig,
437 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400438 break
439 }
440 }
441 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000442 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400443 }
444 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530445 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800446 "reason": "Could-not-get-meterbands-from-flowMetadata",
447 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530448 "meter-id": sq.meterID,
449 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400450 } else if len(meterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000451 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Shrey Baid26912972020-04-16 21:02:31 +0530452 log.Fields{"Bands": meterConfig.Bands,
453 "meter-id": sq.meterID,
454 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530455 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800456 "reason": "Invalid-number-of-bands-in-meter",
457 "meterband-count": len(meterConfig.Bands),
458 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530459 "meter-id": sq.meterID,
460 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400461 }
462 cir := meterConfig.Bands[0].Rate
463 cbs := meterConfig.Bands[0].BurstSize
464 eir := meterConfig.Bands[1].Rate
465 ebs := meterConfig.Bands[1].BurstSize
466 pir := cir + eir
467 pbs := cbs + ebs
468 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
469
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700470 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000471 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400472
npujarec5762e2020-01-01 14:08:48 +0530473 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530474 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
475 log.Fields{"intf-id": sq.intfID,
476 "direction": sq.direction,
477 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478 }
479
salmansiddiqui7ac62132019-08-22 03:58:50 +0000480 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400481 * store the meter id on the KV store, for further reference.
482 */
npujarec5762e2020-01-01 14:08:48 +0530483 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 +0530484 return olterrors.NewErrAdapter("failed-updating-meter-id",
485 log.Fields{"onu-id": sq.onuID,
486 "meter-id": sq.meterID,
487 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400488 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000489 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530490 log.Fields{"direction": Direction,
491 "Meter": meterConfig,
492 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400493 return nil
494}
495
npujarec5762e2020-01-01 14:08:48 +0530496func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000497 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000498
499 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530500 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
501 log.Fields{"intf-id": sq.intfID,
502 "direction": sq.direction,
503 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000504 }
505
Neha Sharma96b7bf22020-06-15 10:37:32 +0000506 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530507 log.Fields{
508 "direction": sq.direction,
509 "TrafficScheds": TrafficSched,
510 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530511 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000512 IntfId: sq.intfID, OnuId: sq.onuID,
513 UniId: sq.uniID, PortNo: sq.uniPort,
514 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000515 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000516 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000517 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530518 "direction": sq.direction,
519 "traffic-queues": trafficQueues,
520 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000521
522 // On receiving the CreateTrafficQueues request, the driver should create corresponding
523 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000524 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530525 log.Fields{"direction": sq.direction,
526 "traffic-queues": trafficQueues,
527 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530528 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000529 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
530 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000531 TrafficQueues: trafficQueues,
532 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530533 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000534 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000535 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530536 "direction": sq.direction,
537 "traffic-queues": trafficQueues,
538 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000539
Esin Karamanccb714b2019-11-29 15:02:06 +0000540 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000541 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000542 if len(multicastTrafficQueues) > 0 {
543 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
544 //assumed that there is only one queue per PON for the multicast service
545 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
546 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000547 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000548 multicastQueuePerPonPort := multicastTrafficQueues[0]
549 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
550 gemPortID: multicastQueuePerPonPort.GemportId,
551 servicePriority: multicastQueuePerPonPort.Priority,
552 }
553 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400554 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
555 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
556 return err
557 }
Shrey Baid26912972020-04-16 21:02:31 +0530558
Neha Sharma96b7bf22020-06-15 10:37:32 +0000559 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000560 }
561 }
562 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000563 return nil
564}
565
salmansiddiqui7ac62132019-08-22 03:58:50 +0000566// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530567func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400568
569 var Direction string
570 var SchedCfg *tp_pb.SchedulerConfig
571 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000572 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530573 log.Fields{
574 "direction": sq.direction,
575 "intf-id": sq.intfID,
576 "onu-id": sq.onuID,
577 "uni-id": sq.uniID,
578 "uni-port": sq.uniPort,
579 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000580 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000581 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400582 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000583 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000584 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400585 Direction = "downstream"
586 }
587
Girish Kumar8f73fe02019-12-09 13:19:37 +0000588 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530589 return olterrors.NewErrNotFound("scheduler-config",
590 log.Fields{
591 "int-id": sq.intfID,
592 "direction": sq.direction,
593 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000594 }
595
npujarec5762e2020-01-01 14:08:48 +0530596 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400597 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530598 return olterrors.NewErrNotFound("meter",
599 log.Fields{
600 "onu-id": sq.onuID,
601 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400602 }
603 if KVStoreMeter == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000604 logger.Warnw(ctx, "no-meter-installed-yet",
Shrey Baid26912972020-04-16 21:02:31 +0530605 log.Fields{
606 "direction": Direction,
607 "intf-id": sq.intfID,
608 "onu-id": sq.onuID,
609 "uni-id": sq.uniID,
610 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400611 return nil
612 }
613 cir := KVStoreMeter.Bands[0].Rate
614 cbs := KVStoreMeter.Bands[0].BurstSize
615 eir := KVStoreMeter.Bands[1].Rate
616 ebs := KVStoreMeter.Bands[1].BurstSize
617 pir := cir + eir
618 pbs := cbs + ebs
619
620 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
621
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700622 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000623 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000624
Neha Sharma96b7bf22020-06-15 10:37:32 +0000625 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000626 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530627 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
628 log.Fields{
629 "intf-id": sq.intfID,
630 "direction": sq.direction,
631 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000632 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400633
npujarec5762e2020-01-01 14:08:48 +0530634 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000635 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
636 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000637 TrafficQueues: TrafficQueues,
638 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000639 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530640 log.Fields{
641 "intf-id": sq.intfID,
642 "traffic-queues": TrafficQueues,
643 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400644 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000645 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530646 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000647 IntfId: sq.intfID, OnuId: sq.onuID,
648 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400649 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000650 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530651 log.Fields{
652 "intf-id": sq.intfID,
653 "traffic-schedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400654 }
655
Neha Sharma96b7bf22020-06-15 10:37:32 +0000656 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000657
658 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400659 * delete the meter id on the KV store.
660 */
npujarec5762e2020-01-01 14:08:48 +0530661 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400662 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530663 return olterrors.NewErrAdapter("unable-to-remove-meter",
664 log.Fields{
665 "onu": sq.onuID,
666 "meter": KVStoreMeter.MeterId,
667 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400668 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000669 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530670 log.Fields{
671 "meter-id": KVStoreMeter.MeterId,
672 "dir": Direction,
673 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400674 return err
675}
676
Gamze Abakafee36392019-10-03 11:17:24 +0000677// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700678func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) (uint32, []uint32, interface{}) {
Gamze Abakafee36392019-10-03 11:17:24 +0000679 var allocIDs []uint32
680 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530681 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530682 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000683 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000684
npujarec5762e2020-01-01 14:08:48 +0530685 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
686 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400687
Neha Sharma96b7bf22020-06-15 10:37:32 +0000688 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530689
Neha Sharma96b7bf22020-06-15 10:37:32 +0000690 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530691 "intf-id": intfID,
692 "onu-id": onuID,
693 "uni-id": uniID,
694 "device-id": f.deviceHandler.device.Id,
695 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530696
Manikkaraj kb1d51442019-07-23 10:41:02 -0400697 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530698 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000699 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000700 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530701 log.Fields{
702 "path": tpPath,
703 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530704 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000705 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530706 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000707 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530708 log.Fields{
709 "error": err,
710 "tp-id": TpID,
711 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000712 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530713 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400714 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
715 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
716 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530717 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000718 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530719 log.Fields{
720 "uni": uni,
721 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530722 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530723 }
Gamze Abakafee36392019-10-03 11:17:24 +0000724
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700725 switch tpInst := techProfileInstance.(type) {
726 case *tp.TechProfile:
727 if UsMeterID != 0 {
728 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
729 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
730 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000731 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700732 log.Fields{
733 "error": err,
734 "meter-id": UsMeterID,
735 "device-id": f.deviceHandler.device.Id})
736 return 0, nil, nil
737 }
738 }
739 if DsMeterID != 0 {
740 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
741 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
742 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000743 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700744 log.Fields{
745 "error": err,
746 "meter-id": DsMeterID,
747 "device-id": f.deviceHandler.device.Id})
748 return 0, nil, nil
749 }
750 }
751 allocID := tpInst.UsScheduler.AllocID
752 for _, gem := range tpInst.UpstreamGemPortAttributeList {
753 gemPortIDs = append(gemPortIDs, gem.GemportID)
754 }
755 allocIDs = appendUnique(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000756
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700757 if tpInstanceExists {
758 return allocID, gemPortIDs, techProfileInstance
759 }
760
761 for _, gemPortID := range gemPortIDs {
762 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
763 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000764 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700765 log.Fields{
766 "alloc-ids": allocIDs,
767 "gemports": allgemPortIDs,
768 "device-id": f.deviceHandler.device.Id})
769 // Send Tconts and GEM ports to KV store
770 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530771 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700772 case *tp.EponProfile:
773 // CreateSchedulerQueues for EPON needs to be implemented here
774 // when voltha-protos for EPON is completed.
775 allocID := tpInst.AllocID
776 for _, gem := range tpInst.UpstreamQueueAttributeList {
777 gemPortIDs = append(gemPortIDs, gem.GemportID)
778 }
779 allocIDs = appendUnique(allocIDs, allocID)
780
781 if tpInstanceExists {
782 return allocID, gemPortIDs, techProfileInstance
783 }
784
785 for _, gemPortID := range gemPortIDs {
786 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
787 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000788 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700789 log.Fields{
790 "alloc-ids": allocIDs,
791 "gemports": allgemPortIDs,
792 "device-id": f.deviceHandler.device.Id})
793 // Send Tconts and GEM ports to KV store
794 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
795 return allocID, gemPortIDs, techProfileInstance
796 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000797 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700798 log.Fields{
799 "tpInst": tpInst})
800 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530801 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530802}
803
npujarec5762e2020-01-01 14:08:48 +0530804func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530805
Neha Sharma96b7bf22020-06-15 10:37:32 +0000806 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530807 log.Fields{
808 "intf-id": intfID,
809 "onu-id": onuID,
810 "uni-id": uniID,
811 "alloc-id": allocID,
812 "gemport-ids": gemPortIDs,
813 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530814 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530815 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000816 logger.Errorw(ctx, "error-while-uploading-allocid-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530817 }
npujarec5762e2020-01-01 14:08:48 +0530818 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000819 logger.Errorw(ctx, "error-while-uploading-gemports-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530820 }
npujarec5762e2020-01-01 14:08:48 +0530821 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000822 logger.Error(ctx, "error-while-uploading-gemtopon-map-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530823 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000824 logger.Infow(ctx, "stored-tconts-and-gem-into-kv-store-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400825 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530826 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400827 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530828}
829
Neha Sharma96b7bf22020-06-15 10:37:32 +0000830func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000831 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530832 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000833 for _, intfID := range techRange.IntfIds {
834 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400835 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000836 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530837 log.Fields{
838 "intf-id": intfID,
839 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530840 }
841 }
842 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400843 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530844 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530845 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800846 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530847 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
848 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530849 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000850 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530851 log.Fields{
852 "numofTech": tpCount,
853 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
854 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530855 return nil
856}
857
npujarec5762e2020-01-01 14:08:48 +0530858func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530859 portNo uint32, uplinkClassifier map[string]interface{},
860 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000861 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700862 uplinkClassifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000863 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530864 log.Fields{
865 "uplinkClassifier": uplinkClassifier,
866 "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800867 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000868 Upstream, logicalFlow, allocID, gemportID, tpID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530869 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530870}
871
npujarec5762e2020-01-01 14:08:48 +0530872func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530873 portNo uint32, downlinkClassifier map[string]interface{},
874 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000875 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700876 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000877 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530878 log.Fields{
879 "downlinkClassifier": downlinkClassifier,
880 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400881 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
882 if vlan, exists := downlinkClassifier[VlanVid]; exists {
883 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700884 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Neha Sharma96b7bf22020-06-15 10:37:32 +0000885 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, intfID, onuID, uniID) {
886 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530887 log.Fields{
888 "flow": logicalFlow,
889 "device-id": f.deviceHandler.device.Id,
890 "onu-id": onuID,
891 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800892 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400893 }
894 }
895 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530896 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400897
Manikkaraj k884c1242019-04-11 16:26:42 +0530898 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700899 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400900 // vlan_vid is a uint32. must be type asserted as such or conversion fails
901 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530902 if ok {
903 downlinkAction[VlanVid] = dlClVid & 0xfff
904 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530905 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530906 "reason": "failed-to-convert-vlanid-classifier",
907 "vlan-id": VlanVid,
908 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530909 }
910
David K. Bainbridge794735f2020-02-11 21:01:37 -0800911 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000912 Downstream, logicalFlow, allocID, gemportID, tpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530913}
914
npujarec5762e2020-01-01 14:08:48 +0530915func (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 +0530916 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000917 allocID uint32, gemPortID uint32, tpID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530918 /* One of the OLT platform (Broadcom BAL) requires that symmetric
919 flows require the same flow_id to be used across UL and DL.
920 Since HSIA flow is the only symmetric flow currently, we need to
921 re-use the flow_id across both direction. The 'flow_category'
922 takes priority over flow_cookie to find any available HSIA_FLOW
923 id for the ONU.
924 */
Neha Sharma96b7bf22020-06-15 10:37:32 +0000925 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530926 log.Fields{
927 "intf-id": intfID,
928 "onu-id": onuID,
929 "uni-id": uniID,
930 "device-id": f.deviceHandler.device.Id,
931 "classifier": classifier,
932 "action": action,
933 "direction": direction,
934 "alloc-id": allocID,
935 "gemport-id": gemPortID,
936 "logicalflow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530937 var vlanPbit uint32 = 0xff // means no pbit
Gamze Abaka724d0852020-03-18 12:10:24 +0000938 var vlanVid uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400939 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000940 vlanPbit = classifier[VlanPcp].(uint32)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000941 logger.Debugw(ctx, "found-pbit-in-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530942 log.Fields{
943 "vlan-pbit": vlanPbit,
944 "intf-id": intfID,
945 "onu-id": onuID,
946 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800947 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000948 logger.Debugw(ctx, "pbit-not-found-in-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530949 log.Fields{
950 "vlan-pcp": VlanPcp,
951 "intf-id": intfID,
952 "onu-id": onuID,
953 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400954 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000955 if _, ok := classifier[VlanVid]; ok {
956 vlanVid = classifier[VlanVid].(uint32)
Shrey Baid26912972020-04-16 21:02:31 +0530957 log.Debugw("found-vlan-in-the-flow",
958 log.Fields{
959 "vlan-vid": vlanVid,
960 "intf-id": intfID,
961 "onu-id": onuID,
962 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000963 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000964 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530965 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000966 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +0530967 log.Fields{
968 "device-id": f.deviceHandler.device.Id,
969 "intf-id": intfID,
970 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800971 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530972 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000973 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530974 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530975 return olterrors.NewErrNotFound("hsia-flow-id",
976 log.Fields{
977 "direction": direction,
978 "device-id": f.deviceHandler.device.Id,
979 "intf-id": intfID,
980 "onu-id": onuID,
981 }, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530982 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800983 classifierProto, err := makeOpenOltClassifierField(classifier)
984 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530985 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530986 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000987 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530988 log.Fields{
989 "classifier": *classifierProto,
990 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000991 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800992 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530993 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530994 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000995 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530996 log.Fields{
997 "action": *actionProto,
998 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +0000999 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301000 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301001 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001002 log.Fields{
1003 "classifier": classifier,
1004 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301005 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001006 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301007 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001008 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
1009 OnuId: int32(onuID),
1010 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +00001011 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +05301012 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001013 AllocId: int32(allocID),
1014 NetworkIntfId: int32(networkIntfID),
1015 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +05301016 Classifier: classifierProto,
1017 Action: actionProto,
1018 Priority: int32(logicalFlow.Priority),
1019 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001020 PortNo: portNo,
1021 TechProfileId: tpID,
1022 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001023 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301024 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301025 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001026 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301027 log.Fields{"direction": direction,
1028 "device-id": f.deviceHandler.device.Id,
1029 "flow": flow,
1030 "intf-id": intfID,
1031 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001032 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
1033 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1034 flow.OnuId,
1035 flow.UniId,
1036 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301037 return olterrors.NewErrPersistence("update", "flow", flowID,
1038 log.Fields{
1039 "flow": flow,
1040 "device-id": f.deviceHandler.device.Id,
1041 "intf-id": intfID,
1042 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001043 }
1044 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301045}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001046
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001047func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1048 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1049 gemPortID uint32, tpID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301050
Neha Sharma96b7bf22020-06-15 10:37:32 +00001051 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301052 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301053 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001054 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301055 "action": action,
1056 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001057 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301058 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301059
1060 // Clear the action map
1061 for k := range action {
1062 delete(action, k)
1063 }
1064
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001065 action[TrapToHost] = true
1066 classifier[UDPSrc] = uint32(68)
1067 classifier[UDPDst] = uint32(67)
1068 classifier[PacketTagType] = SingleTag
1069 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301070
Neha Sharma96b7bf22020-06-15 10:37:32 +00001071 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301072 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001073 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301074 log.Fields{
1075 "device-id": f.deviceHandler.device.Id,
1076 "intf-id": intfID,
1077 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001078 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301079 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301080
David K. Bainbridge794735f2020-02-11 21:01:37 -08001081 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 +05301082
1083 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301084 return olterrors.NewErrNotFound("flow",
1085 log.Fields{
1086 "interface-id": intfID,
1087 "gem-port": gemPortID,
1088 "cookie": flowStoreCookie,
1089 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001090 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301091 }
1092
Neha Sharma96b7bf22020-06-15 10:37:32 +00001093 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301094 log.Fields{
1095 "ul_classifier": classifier,
1096 "ul_action": action,
1097 "uplinkFlowId": flowID,
1098 "intf-id": intfID,
1099 "onu-id": onuID,
1100 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301101
David K. Bainbridge794735f2020-02-11 21:01:37 -08001102 classifierProto, err := makeOpenOltClassifierField(classifier)
1103 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301104 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301105 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001106 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001107 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001108 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301109 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301110 }
1111
David K. Bainbridge794735f2020-02-11 21:01:37 -08001112 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001113 OnuId: int32(onuID),
1114 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301115 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001116 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001117 AllocId: int32(allocID),
1118 NetworkIntfId: int32(networkIntfID),
1119 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301120 Classifier: classifierProto,
1121 Action: actionProto,
1122 Priority: int32(logicalFlow.Priority),
1123 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001124 PortNo: portNo,
1125 TechProfileId: tpID,
1126 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001127 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301128 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001129 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001130 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301131 log.Fields{
1132 "device-id": f.deviceHandler.device.Id,
1133 "flow-id": flowID,
1134 "intf-id": intfID,
1135 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001136 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
1137 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
1138 dhcpFlow.OnuId,
1139 dhcpFlow.UniId,
1140 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301141 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1142 log.Fields{
1143 "flow": dhcpFlow,
1144 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301145 }
1146
David K. Bainbridge794735f2020-02-11 21:01:37 -08001147 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301148}
1149
Esin Karamanae41e2b2019-12-17 18:13:13 +00001150//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301151func (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 +00001152 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32) error {
1153 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001154}
1155
1156//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301157func (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 +00001158 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string, tpID uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001159
Neha Sharma96b7bf22020-06-15 10:37:32 +00001160 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001161 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301162 return olterrors.NewErrNotFound("nni-interface-id",
1163 log.Fields{
1164 "classifier": classifier,
1165 "action": action,
1166 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001167 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001168 }
1169
1170 // Clear the action map
1171 for k := range action {
1172 delete(action, k)
1173 }
1174
1175 action[TrapToHost] = true
1176 classifier[PacketTagType] = SingleTag
1177 delete(classifier, VlanVid)
1178
Neha Sharma96b7bf22020-06-15 10:37:32 +00001179 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301180 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001181 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001182 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001183 }
1184
npujarec5762e2020-01-01 14:08:48 +05301185 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 +00001186
1187 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301188 return olterrors.NewErrNotFound("flow-id",
1189 log.Fields{
1190 "intf-id": intfID,
1191 "oni-id": onuID,
1192 "cookie": flowStoreCookie,
1193 "flow-type": flowType,
1194 "device-id": f.deviceHandler.device.Id,
1195 "onu-id": onuID},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001196 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001197 }
1198
Neha Sharma96b7bf22020-06-15 10:37:32 +00001199 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301200 log.Fields{
1201 "ul_classifier": classifier,
1202 "ul_action": action,
1203 "uplinkFlowId": flowID,
1204 "flowType": flowType,
1205 "device-id": f.deviceHandler.device.Id,
1206 "intf-id": intfID,
1207 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001208
David K. Bainbridge794735f2020-02-11 21:01:37 -08001209 classifierProto, err := makeOpenOltClassifierField(classifier)
1210 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301211 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001212 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001213 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301214 log.Fields{
1215 "classifier": *classifierProto,
1216 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001217 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001218 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301219 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001220 }
1221
David K. Bainbridge794735f2020-02-11 21:01:37 -08001222 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001223 OnuId: int32(onuID),
1224 UniId: int32(uniID),
1225 FlowId: flowID,
1226 FlowType: Upstream,
1227 AllocId: int32(allocID),
1228 NetworkIntfId: int32(networkIntfID),
1229 GemportId: int32(gemPortID),
1230 Classifier: classifierProto,
1231 Action: actionProto,
1232 Priority: int32(logicalFlow.Priority),
1233 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001234 PortNo: portNo,
1235 TechProfileId: tpID,
1236 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001237
David K. Bainbridge794735f2020-02-11 21:01:37 -08001238 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301239 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 -08001240 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001241 logger.Infof(ctx, "%s ul-flow-added-to-device-successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001242
David K. Bainbridge794735f2020-02-11 21:01:37 -08001243 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
1244 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1245 flow.OnuId,
1246 flow.UniId,
1247 flow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301248 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 +00001249 }
1250
David K. Bainbridge794735f2020-02-11 21:01:37 -08001251 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001252}
1253
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001254// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001255func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1256 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1257 gemPortID uint32, vlanID uint32, tpID uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001258 logger.Infow(ctx, "adding-eapol-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301259 log.Fields{
1260 "intf-id": intfID,
1261 "onu-id": onuID,
1262 "port-no": portNo,
1263 "alloc-id": allocID,
1264 "gemport-id": gemPortID,
1265 "vlan-id": vlanID,
1266 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301267
1268 uplinkClassifier := make(map[string]interface{})
1269 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301270
manikkaraj kbf256be2019-03-25 00:13:48 +05301271 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001272 uplinkClassifier[EthType] = uint32(EapEthType)
1273 uplinkClassifier[PacketTagType] = SingleTag
1274 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001275 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301276 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001277 uplinkAction[TrapToHost] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00001278 flowStoreCookie := getFlowStoreCookie(ctx, uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301279 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001280 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301281 "device-id": f.deviceHandler.device.Id,
1282 "onu-id": onuID,
1283 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001284 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301285 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301286 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +00001287 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +05301288 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301289 return olterrors.NewErrNotFound("flow-id",
1290 log.Fields{
1291 "intf-id": intfID,
1292 "onu-id": onuID,
1293 "coookie": flowStoreCookie,
1294 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001295 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301296 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001297 logger.Debugw(ctx, "creating-ul-eapol-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301298 log.Fields{
1299 "ul_classifier": uplinkClassifier,
1300 "ul_action": uplinkAction,
1301 "uplinkFlowId": uplinkFlowID,
1302 "device-id": f.deviceHandler.device.Id,
1303 "intf-id": intfID,
1304 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301305
David K. Bainbridge794735f2020-02-11 21:01:37 -08001306 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1307 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301308 return olterrors.NewErrInvalidValue(log.Fields{
1309 "classifier": uplinkClassifier,
1310 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301311 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001312 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301313 log.Fields{
1314 "classifier": *classifierProto,
1315 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001316 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001317 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301318 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301319 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001320 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301321 log.Fields{
1322 "action": *actionProto,
1323 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001324 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301325 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301326 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001327 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301328 "action": action,
1329 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001330 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301331 }
1332
David K. Bainbridge794735f2020-02-11 21:01:37 -08001333 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001334 OnuId: int32(onuID),
1335 UniId: int32(uniID),
1336 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001337 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001338 AllocId: int32(allocID),
1339 NetworkIntfId: int32(networkIntfID),
1340 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301341 Classifier: classifierProto,
1342 Action: actionProto,
1343 Priority: int32(logicalFlow.Priority),
1344 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001345 PortNo: portNo,
1346 TechProfileId: tpID,
1347 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001348 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301349 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001350 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001351 logger.Infow(ctx, "eapol-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301352 log.Fields{
1353 "device-id": f.deviceHandler.device.Id,
1354 "onu-id": onuID,
1355 "intf-id": intfID,
1356 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001357 flowCategory := "EAPOL"
1358 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1359 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1360 upstreamFlow.OnuId,
1361 upstreamFlow.UniId,
1362 upstreamFlow.FlowId,
1363 /* lowCategory, */
1364 flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301365 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1366 log.Fields{
1367 "flow": upstreamFlow,
1368 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301369 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001370 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301371}
1372
David K. Bainbridge794735f2020-02-11 21:01:37 -08001373func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001374 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001375
1376 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1377 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1378 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001379 if vlanID != ReservedVlan {
1380 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001381 classifier.OVid = vid
1382 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301383 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001384 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1385 vid := uint32(metadata)
1386 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001387 classifier.IVid = vid
1388 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301389 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301390 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001391 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301392 classifier.OPbits = vlanPcp
1393 } else {
1394 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301395 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001396 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1397 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1398 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1399 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001400 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001401 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1402 classifier.PktTagType = pktTagType
1403
1404 switch pktTagType {
1405 case SingleTag:
1406 case DoubleTag:
1407 case Untagged:
1408 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001409 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301410 }
1411 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001412 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301413}
1414
Gamze Abaka724d0852020-03-18 12:10:24 +00001415func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001416 var actionCmd openoltpb2.ActionCmd
1417 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301418 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001419 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301420 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001421 if _, ok := actionInfo[VlanPcp]; ok {
1422 action.Cmd.RemarkInnerPbits = true
1423 action.IPbits = actionInfo[VlanPcp].(uint32)
1424 if _, ok := actionInfo[VlanVid]; ok {
1425 action.Cmd.TranslateInnerTag = true
1426 action.IVid = actionInfo[VlanVid].(uint32)
1427 }
1428 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001429 } else if _, ok := actionInfo[PushVlan]; ok {
1430 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301431 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001432 if _, ok := actionInfo[VlanPcp]; ok {
1433 action.OPbits = actionInfo[VlanPcp].(uint32)
1434 action.Cmd.RemarkOuterPbits = true
1435 if _, ok := classifierInfo[VlanVid]; ok {
1436 action.IVid = classifierInfo[VlanVid].(uint32)
1437 action.Cmd.TranslateInnerTag = true
1438 }
1439 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001440 } else if _, ok := actionInfo[TrapToHost]; ok {
1441 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301442 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001443 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301444 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001445 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301446}
1447
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001448// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001449func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1450 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301451}
1452
Gamze Abakafee36392019-10-03 11:17:24 +00001453// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301454func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1455 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001456 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1457
Gamze Abakafee36392019-10-03 11:17:24 +00001458 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301459 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001460 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301461 // return err
1462 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001463 }
Shrey Baid26912972020-04-16 21:02:31 +05301464 log.Debugw("tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001465 }
1466 return nil
1467}
1468
1469// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301470func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001471 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001472 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001473 }
npujarec5762e2020-01-01 14:08:48 +05301474 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301475 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1476 log.Fields{
1477 "tp-id": tpID,
1478 "uni-port-name": uniPortName,
1479 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001480 }
1481 return nil
1482}
1483
Neha Sharma96b7bf22020-06-15 10:37:32 +00001484func getFlowStoreCookie(ctx context.Context, classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301485 if len(classifier) == 0 { // should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00001486 logger.Error(ctx, "invalid-classfier-object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301487 return 0
1488 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001489 logger.Debugw(ctx, "generating-flow-store-cookie",
Shrey Baid26912972020-04-16 21:02:31 +05301490 log.Fields{
1491 "classifier": classifier,
1492 "gemport-id": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301493 var jsonData []byte
1494 var flowString string
1495 var err error
1496 // TODO: Do we need to marshall ??
1497 if jsonData, err = json.Marshal(classifier); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001498 logger.Error(ctx, "failed-to-encode-classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301499 return 0
1500 }
1501 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001502 if gemPortID != 0 {
1503 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301504 }
1505 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001506 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301507 hash := big.NewInt(0)
1508 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301509 generatedHash := hash.Uint64()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001510 logger.Debugw(ctx, "hash-generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301511 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301512}
1513
npujarec5762e2020-01-01 14:08:48 +05301514func (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 +05301515 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001516 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001517 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1518 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1519 */
1520 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001521 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001522 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001523 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001524 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001525 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301526 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001527 if existingFlows != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001528 logger.Debugw(ctx, "flow-exists-for-given-flowID--appending-it-to-current-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301529 log.Fields{
1530 "flow-id": flow.FlowId,
1531 "device-id": f.deviceHandler.device.Id,
1532 "intf-id": intfID,
1533 "onu-id": flow.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001534 //for _, f := range *existingFlows {
1535 // flows = append(flows, f)
1536 //}
1537 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001538 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001539 logger.Debugw(ctx, "updated-flows-for-given-flowID-and-onuid",
Shrey Baid26912972020-04-16 21:02:31 +05301540 log.Fields{
1541 "updatedflow": flows,
1542 "flow-id": flow.FlowId,
1543 "onu-id": flow.OnuId,
1544 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +05301545 return &flows
1546}
1547
npujarec5762e2020-01-01 14:08:48 +05301548func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(ctx context.Context, intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001549 logger.Debugw(ctx, "storing-flow(s)-into-kv-store", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301550 "flow-id": flowID,
1551 "device-id": f.deviceHandler.device.Id,
1552 "intf-id": intfID,
1553 "onu-id": onuID})
npujarec5762e2020-01-01 14:08:48 +05301554 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001555 logger.Warnw(ctx, "error-while-storing-flow-into-kv-store", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301556 "device-id": f.deviceHandler.device.Id,
1557 "onu-id": onuID,
1558 "intf-id": intfID,
1559 "flow-id": flowID})
manikkaraj k17652a72019-05-06 09:06:36 -04001560 return err
1561 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001562 logger.Infow(ctx, "stored-flow(s)-into-kv-store-successfully!", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301563 "device-id": f.deviceHandler.device.Id,
1564 "onu-id": onuID,
1565 "intf-id": intfID,
1566 "flow-id": flowID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301567 return nil
1568}
1569
David K. Bainbridge794735f2020-02-11 21:01:37 -08001570func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001571
1572 var intfID uint32
1573 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1574 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1575 */
1576 if deviceFlow.AccessIntfId != -1 {
1577 intfID = uint32(deviceFlow.AccessIntfId)
1578 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001579 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001580 intfID = uint32(deviceFlow.NetworkIntfId)
1581 }
1582
Neha Sharma96b7bf22020-06-15 10:37:32 +00001583 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301584 "flow": *deviceFlow,
1585 "device-id": f.deviceHandler.device.Id,
1586 "intf-id": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301587 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001588
1589 st, _ := status.FromError(err)
1590 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001591 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001592 "err": err,
1593 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301594 "device-id": f.deviceHandler.device.Id,
1595 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001596 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301597 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001598
1599 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001600 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301601 log.Fields{"err": err,
1602 "device-flow": deviceFlow,
1603 "device-id": f.deviceHandler.device.Id,
1604 "intf-id": intfID})
npujarec5762e2020-01-01 14:08:48 +05301605 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001606 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001607 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301608 if deviceFlow.GemportId != -1 {
1609 // No need to register the flow if it is a trap on nni flow.
Kent Hagermane6ff1012020-07-14 15:07:53 -04001610 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1611 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1612 return err
1613 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301614 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001615 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301616 log.Fields{
1617 "flow": *deviceFlow,
1618 "device-id": f.deviceHandler.device.Id,
1619 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001620 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001621}
1622
Neha Sharma96b7bf22020-06-15 10:37:32 +00001623func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1624 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301625 log.Fields{
1626 "flow": *deviceFlow,
1627 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001628 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1629 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001630 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001631 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301632 log.Fields{
1633 "err": err,
1634 "deviceFlow": deviceFlow,
1635 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001636 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001637 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001638 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001639 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001640
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001641 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001642 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001643 "of-flow-id": ofFlowID,
1644 "flow": *deviceFlow,
1645 "device-id": f.deviceHandler.device.Id,
1646 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001647 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301648}
1649
David K. Bainbridge794735f2020-02-11 21:01:37 -08001650func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001651
1652 classifierInfo := make(map[string]interface{})
1653 actionInfo := make(map[string]interface{})
1654
1655 classifierInfo[EthType] = uint32(LldpEthType)
1656 classifierInfo[PacketTagType] = Untagged
1657 actionInfo[TrapToHost] = true
1658
1659 // LLDP flow is installed to trap LLDP packets on the NNI port.
1660 // We manage flow_id resource pool on per PON port basis.
1661 // Since this situation is tricky, as a hack, we pass the NNI port
1662 // index (network_intf_id) as PON port Index for the flow_id resource
1663 // pool. Also, there is no ONU Id available for trapping LLDP packets
1664 // on NNI port, use onu_id as -1 (invalid)
1665 // ****************** CAVEAT *******************
1666 // This logic works if the NNI Port Id falls within the same valid
1667 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1668 // we need to have a re-look at this.
1669 // *********************************************
1670
1671 var onuID = -1
1672 var uniID = -1
1673 var gemPortID = -1
1674
Neha Sharma96b7bf22020-06-15 10:37:32 +00001675 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001676 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301677 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001678 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001679 var flowStoreCookie = getFlowStoreCookie(ctx, classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301680 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001681 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001682 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001683 }
npujarec5762e2020-01-01 14:08:48 +05301684 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001685
1686 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301687 return olterrors.NewErrNotFound("flow-id",
1688 log.Fields{
1689 "interface-id": networkInterfaceID,
1690 "onu-id": onuID,
1691 "uni-id": uniID,
1692 "gem-port-id": gemPortID,
1693 "cookie": flowStoreCookie,
1694 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001695 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001696 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001697 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1698 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301699 return olterrors.NewErrInvalidValue(
1700 log.Fields{
1701 "classifier": classifierInfo,
1702 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001703 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001704 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301705 log.Fields{
1706 "classifier": *classifierProto,
1707 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001708 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001709 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301710 return olterrors.NewErrInvalidValue(
1711 log.Fields{
1712 "action": actionInfo,
1713 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001714 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001715 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301716 log.Fields{
1717 "action": *actionProto,
1718 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001719
1720 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1721 OnuId: int32(onuID), // OnuId not required
1722 UniId: int32(uniID), // UniId not used
1723 FlowId: flowID,
1724 FlowType: Downstream,
1725 NetworkIntfId: int32(networkInterfaceID),
1726 GemportId: int32(gemPortID),
1727 Classifier: classifierProto,
1728 Action: actionProto,
1729 Priority: int32(flow.Priority),
1730 Cookie: flow.Cookie,
1731 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001732 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301733 return olterrors.NewErrFlowOp("add", flowID,
1734 log.Fields{
1735 "flow": downstreamflow,
1736 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001737 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001738 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301739 log.Fields{
1740 "device-id": f.deviceHandler.device.Id,
1741 "onu-id": onuID,
1742 "flow-id": flowID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001743 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1744 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1745 int32(onuID),
1746 int32(uniID),
1747 flowID, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301748 return olterrors.NewErrPersistence("update", "flow", flowID,
1749 log.Fields{
1750 "flow": downstreamflow,
1751 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001752 }
1753 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301754}
1755
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001756func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1757 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001758}
1759
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001760//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001761func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001762 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1763 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1764 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001765 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301766 log.Fields{
1767 "intf-id": intfID,
1768 "onu-id": onuID,
1769 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001770 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001771 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301772 return nil, olterrors.NewErrNotFound("onu-child-device",
1773 log.Fields{
1774 "onu-id": onuID,
1775 "intf-id": intfID,
1776 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001777 }
1778 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1779 //better to ad the device to cache here.
1780 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1781 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001782 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301783 log.Fields{
1784 "intf-id": intfID,
1785 "onu-id": onuID,
1786 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001787 }
1788
1789 return onuDev.(*OnuDevice), nil
1790}
1791
1792//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001793func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1794 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301795 log.Fields{
1796 "pon-port": intfID,
1797 "onu-id": onuID,
1798 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001799 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001800 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001801 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301802 return nil, olterrors.NewErrNotFound("onu",
1803 log.Fields{
1804 "interface-id": parentPortNo,
1805 "onu-id": onuID,
1806 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001807 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301808 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001809 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301810 log.Fields{
1811 "device-id": f.deviceHandler.device.Id,
1812 "child_device_id": onuDevice.Id,
1813 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301814 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301815}
1816
Neha Sharma96b7bf22020-06-15 10:37:32 +00001817func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1818 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301819 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001820 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301821 log.Fields{
1822 "intf-id": intfID,
1823 "onu-id": onuID,
1824 "uni-id": uniID,
1825 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001826 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301827 }
1828
1829 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001830 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301831 log.Fields{
1832 "msg": *delGemPortMsg,
1833 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301834 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1835 delGemPortMsg,
1836 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301837 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001838 onuDev.deviceType,
1839 onuDev.deviceID,
1840 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301841 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1842 log.Fields{
1843 "from-adapter": f.deviceHandler.device.Type,
1844 "to-adapter": onuDev.deviceType,
1845 "onu-id": onuDev.deviceID,
1846 "proxyDeviceID": onuDev.proxyDeviceID,
1847 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301848 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001849 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301850 log.Fields{
1851 "msg": delGemPortMsg,
1852 "from-adapter": f.deviceHandler.device.Type,
1853 "to-adapter": onuDev.deviceType,
1854 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301855 return nil
1856}
1857
Neha Sharma96b7bf22020-06-15 10:37:32 +00001858func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1859 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301860 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001861 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301862 log.Fields{
1863 "intf-id": intfID,
1864 "onu-id": onuID,
1865 "uni-id": uniID,
1866 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001867 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301868 }
1869
1870 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001871 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301872 log.Fields{
1873 "msg": *delTcontMsg,
1874 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301875 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1876 delTcontMsg,
1877 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301878 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001879 onuDev.deviceType,
1880 onuDev.deviceID,
1881 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301882 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1883 log.Fields{
1884 "from-adapter": f.deviceHandler.device.Type,
1885 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1886 "proxyDeviceID": onuDev.proxyDeviceID,
1887 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301888 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001889 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301890 log.Fields{
1891 "msg": delTcontMsg,
1892 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301893 return nil
1894}
1895
Neha Sharma96b7bf22020-06-15 10:37:32 +00001896func (f *OpenOltFlowMgr) deletePendingFlows(ctx context.Context, Intf uint32, onuID int32, uniID int32) {
Girish Gowdra3d633032019-12-10 16:37:05 +05301897 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1898 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1899 if val.(int) > 0 {
1900 pnFlDels := val.(int) - 1
1901 if pnFlDels > 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001902 logger.Debugw(ctx, "flow-delete-succeeded--more-pending",
Shrey Baid26912972020-04-16 21:02:31 +05301903 log.Fields{
1904 "intf": Intf,
1905 "onu-id": onuID,
1906 "uni-id": uniID,
1907 "currpendingflowcnt": pnFlDels,
1908 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301909 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1910 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001911 logger.Debugw(ctx, "all-pending-flow-deletes-handled--removing-entry-from-map",
Shrey Baid26912972020-04-16 21:02:31 +05301912 log.Fields{
1913 "intf": Intf,
1914 "onu-id": onuID,
1915 "uni-id": uniID,
1916 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301917 f.pendingFlowDelete.Delete(pnFlDelKey)
1918 }
1919 }
1920 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001921 logger.Debugw(ctx, "no-pending-delete-flows-found",
Shrey Baid26912972020-04-16 21:02:31 +05301922 log.Fields{
1923 "intf": Intf,
1924 "onu-id": onuID,
1925 "uni-id": uniID,
1926 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301927
1928 }
1929
1930}
1931
Girish Gowdrac3037402020-01-22 20:29:53 +05301932// Once the gemport is released for a given onu, it also has to be cleared from local cache
1933// which was used for deriving the gemport->logicalPortNo during packet-in.
1934// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1935// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001936func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001937
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001938 f.onuGemInfoLock.Lock()
1939 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001940
Neha Sharma96b7bf22020-06-15 10:37:32 +00001941 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301942 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001943 "gem-port-id": gemPortID,
1944 "intf-id": intfID,
1945 "onu-id": onuID,
1946 "device-id": f.deviceHandler.device.Id,
1947 "onu-gem": f.onuGemInfo[intfID]})
Girish Gowdrac3037402020-01-22 20:29:53 +05301948 onugem := f.onuGemInfo[intfID]
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001949deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001950 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301951 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001952 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301953 // If the gemport is found, delete it from local cache.
1954 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001955 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1956 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001957 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301958 log.Fields{
1959 "intf-id": intfID,
1960 "onu-id": onuID,
1961 "deletedgemport-id": gemPortID,
1962 "gemports": onu.GemPorts,
1963 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001964 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301965 }
1966 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001967 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301968 }
1969 }
1970}
1971
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301972//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001973// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301974func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301975 gemPortID int32, flowID uint32, flowDirection string,
1976 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001977
Neha Sharma96b7bf22020-06-15 10:37:32 +00001978 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001979 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301980 return olterrors.NewErrNotFound("tp-id",
1981 log.Fields{
1982 "flow": flow,
1983 "intf": Intf,
1984 "onu-id": onuID,
1985 "uni-id": uniID,
1986 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001987 }
Gamze Abakafee36392019-10-03 11:17:24 +00001988
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001989 if len(updatedFlows) >= 0 {
1990 // There are still flows referencing the same flow_id.
1991 // So the flow should not be freed yet.
1992 // For ex: Case of HSIA where same flow is shared
1993 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00001994 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001995 _ = olterrors.NewErrPersistence("update", "flow", flowID,
Shrey Baid26912972020-04-16 21:02:31 +05301996 log.Fields{
1997 "flow": updatedFlows,
1998 "device-id": f.deviceHandler.device.Id}, err).Log()
Girish Kumarf26e4882020-03-05 06:49:10 +00001999 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002000 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05302001 // Do this for subscriber flows only (not trap from NNI flows)
2002 if onuID != -1 && uniID != -1 {
2003 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
2004 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002005 logger.Debugw(ctx, "creating-entry-for-pending-flow-delete",
Shrey Baid26912972020-04-16 21:02:31 +05302006 log.Fields{
2007 "flow-id": flowID,
2008 "intf": Intf,
2009 "onu-id": onuID,
2010 "uni-id": uniID,
2011 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302012 f.pendingFlowDelete.Store(pnFlDelKey, 1)
2013 } else {
2014 pnFlDels := val.(int) + 1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002015 logger.Debugw(ctx, "updating-flow-delete-entry",
Shrey Baid26912972020-04-16 21:02:31 +05302016 log.Fields{
2017 "flow-id": flowID,
2018 "intf": Intf,
2019 "onu-id": onuID,
2020 "uni-id": uniID,
2021 "currPendingFlowCnt": pnFlDels,
2022 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302023 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
2024 }
2025
Neha Sharma96b7bf22020-06-15 10:37:32 +00002026 defer f.deletePendingFlows(ctx, Intf, onuID, uniID)
Girish Gowdra3d633032019-12-10 16:37:05 +05302027 }
2028
Neha Sharma96b7bf22020-06-15 10:37:32 +00002029 logger.Debugw(ctx, "releasing-flow-id-to-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302030 log.Fields{
2031 "Intf": Intf,
2032 "onu-id": onuID,
2033 "uni-id": uniID,
2034 "flow-id": flowID,
2035 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302036 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002037
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002038 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002039 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
2040 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
Shrey Baid26912972020-04-16 21:02:31 +05302041 log.Fields{
2042 "TP-PATH": tpPath,
2043 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302044 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00002045 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +05302046 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
2047 log.Fields{
2048 "tp-id": tpID,
2049 "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002050 }
2051
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302052 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00002053 if f.isGemPortUsedByAnotherFlow(gemPK) {
2054 flowIDs := f.flowsUsedByGemPort[gemPK]
2055 for i, flowIDinMap := range flowIDs {
2056 if flowIDinMap == flowID {
2057 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302058 // everytime flowsUsedByGemPort cache is updated the same should be updated
2059 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002060 f.flowsUsedByGemPort[gemPK] = flowIDs
Kent Hagermane6ff1012020-07-14 15:07:53 -04002061 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs); err != nil {
2062 return err
2063 }
Gamze Abakafee36392019-10-03 11:17:24 +00002064 break
2065 }
2066 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002067 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
Shrey Baid26912972020-04-16 21:02:31 +05302068 log.Fields{
2069 "gemport-id": gemPortID,
2070 "usedByFlows": flowIDs,
2071 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302072 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00002073 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002074 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05302075 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002076 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
2077 // 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 +05302078 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002079 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002080 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302081 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
2082 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002083 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05302084 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
2085 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002086 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05302087 // Delete the gem port on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002088 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
2089 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302090 log.Fields{
2091 "err": err,
2092 "intf": Intf,
2093 "onu-id": onuID,
2094 "uni-id": uniID,
2095 "device-id": f.deviceHandler.device.Id,
2096 "gemport-id": gemPortID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302097 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002098 switch techprofileInst := techprofileInst.(type) {
2099 case *tp.TechProfile:
2100 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
2101 if !ok {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002102 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
2103 logger.Warn(ctx, err)
2104 }
2105 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2106 logger.Warn(ctx, err)
2107 }
2108 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
2109 logger.Warn(ctx, err)
2110 }
2111 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
2112 logger.Warn(ctx, err)
2113 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002114 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
2115 // Delete the TCONT on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002116 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
2117 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002118 log.Fields{
2119 "intf": Intf,
2120 "onu-id": onuID,
2121 "uni-id": uniID,
2122 "device-id": f.deviceHandler.device.Id,
2123 "alloc-id": techprofileInst.UsScheduler.AllocID})
2124 }
2125 }
2126 case *tp.EponProfile:
Kent Hagermane6ff1012020-07-14 15:07:53 -04002127 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
2128 logger.Warn(ctx, err)
2129 }
2130 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2131 logger.Warn(ctx, err)
2132 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002133 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302134 // Delete the TCONT on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002135 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.AllocID), tpPath); err != nil {
2136 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302137 log.Fields{
2138 "intf": Intf,
2139 "onu-id": onuID,
2140 "uni-id": uniID,
2141 "device-id": f.deviceHandler.device.Id,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002142 "alloc-id": techprofileInst.AllocID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302143 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002144 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002145 logger.Errorw(ctx, "error-unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002146 log.Fields{
2147 "techprofileInst": techprofileInst})
Gamze Abakafee36392019-10-03 11:17:24 +00002148 }
2149 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002150 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302151 return nil
2152}
2153
David K. Bainbridge794735f2020-02-11 21:01:37 -08002154// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302155func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302156
Neha Sharma96b7bf22020-06-15 10:37:32 +00002157 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302158 log.Fields{
2159 "flowDirection": flowDirection,
2160 "flow": *flow,
2161 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002162
2163 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05302164 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002165 return
2166 }
2167
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302168 classifierInfo := make(map[string]interface{})
2169
Neha Sharma96b7bf22020-06-15 10:37:32 +00002170 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302171 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002172 logger.Error(ctx, err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302173 return
2174 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302175
David K. Bainbridge794735f2020-02-11 21:01:37 -08002176 onuID := int32(onu)
2177 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302178
2179 for _, field := range flows.GetOfbFields(flow) {
2180 if field.Type == flows.IP_PROTO {
2181 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002182 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302183 }
2184 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002185 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302186 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002187 "flow-id": flow.Id,
2188 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302189 "onu-id": onuID,
2190 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302191
2192 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2193 onuID = -1
2194 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002195 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2196 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002197 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002198 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002199 log.Fields{
2200 "port-number": inPort,
2201 "error": err})
2202 return
2203 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302204 }
npujarec5762e2020-01-01 14:08:48 +05302205 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002206 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302207 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302208 if flowInfo == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002209 logger.Debugw(ctx, "no-flowinfo-found-in-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302210 log.Fields{
2211 "intf": Intf,
2212 "onu-id": onuID,
2213 "uni-id": uniID,
2214 "flow-id": flowID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302215 return
2216 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302217
Kent Hagermane6ff1012020-07-14 15:07:53 -04002218 updatedFlows := *flowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302219 for i, storedFlow := range updatedFlows {
2220 if flow.Id == storedFlow.LogicalFlowID {
2221 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002222 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002223 // DKB
Neha Sharma96b7bf22020-06-15 10:37:32 +00002224 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2225 logger.Errorw(ctx, "failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002226 return
2227 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002228 logger.Info(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002229 "flow-id": flow.Id,
2230 "stored-flow": storedFlow,
2231 "device-id": f.deviceHandler.device.Id,
2232 "stored-flow-id": flowID,
2233 "onu-id": onuID,
2234 "intf": Intf,
2235 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08002236 //Remove the Flow from FlowInfo
2237 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
2238 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
2239 flowID, flowDirection, portNum, updatedFlows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002240 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002241 "flow-id": flow.Id,
2242 "stored-flow": storedFlow,
2243 "device-id": f.deviceHandler.device.Id,
2244 "stored-flow-id": flowID,
2245 "onu-id": onuID,
2246 "intf": Intf,
2247 })
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302248 return
2249 }
2250 }
2251 }
2252 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002253}
2254
Esin Karamanccb714b2019-11-29 15:02:06 +00002255//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
2256// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05302257func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002258 classifierInfo := make(map[string]interface{})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002259 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00002260 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002261
2262 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002263 logger.Warnw(ctx, "no-inport-found--cannot-release-resources-of-the-multicast-flow", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002264 return
2265 }
2266
Esin Karamanccb714b2019-11-29 15:02:06 +00002267 var onuID = int32(NoneOnuID)
2268 var uniID = int32(NoneUniID)
2269 var flowID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00002270
npujarec5762e2020-01-01 14:08:48 +05302271 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002272
2273 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302274 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002275 if flowInfo == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002276 logger.Debugw(ctx, "no-multicast-flowinfo-found-in-the-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302277 log.Fields{
2278 "intf": networkInterfaceID,
2279 "onu-id": onuID,
2280 "uni-id": uniID,
2281 "flow-id": flowID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002282 continue
2283 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002284 updatedFlows := *flowInfo
Esin Karamanccb714b2019-11-29 15:02:06 +00002285 for i, storedFlow := range updatedFlows {
2286 if flow.Id == storedFlow.LogicalFlowID {
2287 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002288 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302289 log.Fields{
2290 "flow": storedFlow,
2291 "flow-id": flow.Id,
2292 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002293 //remove from device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002294 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002295 // DKB
Neha Sharma96b7bf22020-06-15 10:37:32 +00002296 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002297 log.Fields{
2298 "flow-id": flow.Id,
2299 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002300 return
2301 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002302 logger.Infow(ctx, "multicast-flow-removed-from-device-successfully", log.Fields{"flow-id": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002303 //Remove the Flow from FlowInfo
2304 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05302305 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002306 logger.Errorw(ctx, "failed-to-delete-multicast-flow-from-the-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302307 log.Fields{"flow": storedFlow,
2308 "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002309 return
2310 }
2311 //release flow id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002312 logger.Debugw(ctx, "releasing-multicast-flow-id",
Shrey Baid26912972020-04-16 21:02:31 +05302313 log.Fields{"flow-id": flowID,
2314 "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05302315 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002316 }
2317 }
2318 }
2319}
2320
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002321//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002322func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002323 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302324 var direction string
2325 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002326
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302327 for _, action := range flows.GetActions(flow) {
2328 if action.Type == flows.OUTPUT {
2329 if out := action.GetOutput(); out != nil {
2330 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002331 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302332 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002333 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002334 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002335 }
2336 }
2337 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002338
2339 if flows.HasGroup(flow) {
2340 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07002341 f.clearFlowFromResourceManager(ctx, flow, direction)
2342 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002343 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302344 direction = Upstream
2345 } else {
2346 direction = Downstream
2347 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302348
Neha Sharma96b7bf22020-06-15 10:37:32 +00002349 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002350 if err != nil {
2351 return err
2352 }
2353
2354 userKey := tpLockKey{intfID, onuID, uniID}
2355
2356 // Serialize flow removes on a per subscriber basis
2357 if f.perUserFlowHandleLock.TryLock(userKey) {
2358 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
2359 f.perUserFlowHandleLock.Unlock(userKey)
2360 } else {
2361 // Ideally this should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00002362 logger.Errorw(ctx, "failed-to-acquire-lock-to-remove-flow--remove-aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07002363 return errors.New("failed-to-acquire-per-user-lock")
2364 }
2365
2366 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002367}
2368
Girish Gowdra3d633032019-12-10 16:37:05 +05302369func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
2370 uniID uint32, ch chan bool) {
2371 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2372 for {
2373 select {
2374 case <-time.After(20 * time.Millisecond):
2375 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002376 logger.Debug(ctx, "pending-flow-deletes-completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05302377 ch <- true
2378 return
2379 }
2380 case <-ctx.Done():
Neha Sharma96b7bf22020-06-15 10:37:32 +00002381 logger.Error(ctx, "flow-delete-wait-handler-routine-canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05302382 return
2383 }
2384 }
2385}
2386
Esin Karamanae41e2b2019-12-17 18:13:13 +00002387//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2388func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2389 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2390 if ethType, ok := classifierInfo[EthType]; ok {
2391 if ethType.(uint32) == IPv4EthType {
2392 if ipProto, ok := classifierInfo[IPProto]; ok {
2393 if ipProto.(uint32) == IgmpProto {
2394 return true
2395 }
2396 }
2397 }
2398 }
2399 }
2400 return false
2401}
2402
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002403// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302404// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002405func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002406 classifierInfo := make(map[string]interface{})
2407 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002408 var UsMeterID uint32
2409 var DsMeterID uint32
2410
Neha Sharma96b7bf22020-06-15 10:37:32 +00002411 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302412 log.Fields{
2413 "flow": flow,
2414 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002415 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002416
Neha Sharma96b7bf22020-06-15 10:37:32 +00002417 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002418 if err != nil {
2419 // Error logging is already done in the called function
2420 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002421 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302422 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002423
Esin Karamanccb714b2019-11-29 15:02:06 +00002424 if flows.HasGroup(flow) {
2425 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002426 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002427 }
2428
manikkaraj k17652a72019-05-06 09:06:36 -04002429 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002430 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002431 if err != nil {
2432 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002433 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002434 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002435
Neha Sharma96b7bf22020-06-15 10:37:32 +00002436 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302437 log.Fields{
2438 "classifierinfo_inport": classifierInfo[InPort],
2439 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002440 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002441
Humera Kouser94d7a842019-08-25 19:04:32 -04002442 if ethType, ok := classifierInfo[EthType]; ok {
2443 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002444 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002445 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002446 }
2447 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002448 if ipProto, ok := classifierInfo[IPProto]; ok {
2449 if ipProto.(uint32) == IPProtoDhcp {
2450 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302451 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002452 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002453 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002454 }
2455 }
2456 }
2457 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002458 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002459 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002460 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002461 }
A R Karthick1f85b802019-10-11 05:06:05 +00002462
Neha Sharma96b7bf22020-06-15 10:37:32 +00002463 f.deviceHandler.AddUniPortToOnu(ctx, intfID, onuID, portNo)
npujarec5762e2020-01-01 14:08:48 +05302464 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002465
Neha Sharma96b7bf22020-06-15 10:37:32 +00002466 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002467 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302468 return olterrors.NewErrNotFound("tpid-for-flow",
2469 log.Fields{
2470 "flow": flow,
2471 "intf-id": IntfID,
2472 "onu-id": onuID,
2473 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002474 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002475 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302476 log.Fields{
2477 "tp-id": TpID,
2478 "intf-id": intfID,
2479 "onu-id": onuID,
2480 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002481 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002482 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002483 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002484 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002485 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002486 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002487
2488 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302489
2490 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2491 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002492 logger.Debugw(ctx, "no-pending-flows-found--going-ahead-with-flow-install",
Shrey Baid26912972020-04-16 21:02:31 +05302493 log.Fields{
2494 "intf-id": intfID,
2495 "onu-id": onuID,
2496 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302497 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302498 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05302499 pendingFlowDelComplete := make(chan bool)
2500 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
2501 select {
2502 case <-pendingFlowDelComplete:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002503 logger.Debugw(ctx, "all-pending-flow-deletes-completed",
Shrey Baid26912972020-04-16 21:02:31 +05302504 log.Fields{
2505 "intf-id": intfID,
2506 "onu-id": onuID,
2507 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302508 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302509
2510 case <-time.After(10 * time.Second):
Shrey Baid26912972020-04-16 21:02:31 +05302511 return olterrors.NewErrTimeout("pending-flow-deletes",
2512 log.Fields{
2513 "intf-id": intfID,
2514 "onu-id": onuID,
2515 "uni-id": uniID}, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +05302516 }
2517 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002518 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002519}
2520
Esin Karamanccb714b2019-11-29 15:02:06 +00002521// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002522func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002523 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002524 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302525 "classifier-info": classifierInfo,
2526 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002527
Esin Karaman65409d82020-03-18 10:58:18 +00002528 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002529 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002530 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002531 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002532 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
2533 //otherwise, classification is based on ipv4_dst by default.
2534 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
2535 mcastFlowClassificationByEthDst := false
2536
2537 if mcastFlowClassificationByEthDst {
2538 //replace ipDst with ethDst
2539 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
2540 flows.IsMulticastIp(ipv4Dst.(uint32)) {
2541 // replace ipv4_dst classifier with eth_dst
2542 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
2543 delete(classifierInfo, Ipv4Dst)
2544 classifierInfo[EthDst] = multicastMac
Neha Sharma96b7bf22020-06-15 10:37:32 +00002545 logger.Debugw(ctx, "multicast-ip-to-mac-conversion-success",
Shrey Baid26912972020-04-16 21:02:31 +05302546 log.Fields{
2547 "ip:": ipv4Dst.(uint32),
2548 "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002549 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002550 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002551 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002552
David K. Bainbridge794735f2020-02-11 21:01:37 -08002553 onuID := NoneOnuID
2554 uniID := NoneUniID
2555 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00002556
Neha Sharma96b7bf22020-06-15 10:37:32 +00002557 flowStoreCookie := getFlowStoreCookie(ctx, classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302558 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002559 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002560 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002561 }
npujarec5762e2020-01-01 14:08:48 +05302562 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00002563 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302564 return olterrors.NewErrNotFound("multicast-flow-id",
2565 log.Fields{
2566 "interface-id": networkInterfaceID,
2567 "onu-id": onuID,
2568 "uni-id": uniID,
2569 "gem-port-id": gemPortID,
2570 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002571 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002572 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002573 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2574 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002575 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002576 }
2577 groupID := actionInfo[GroupID].(uint32)
2578 multicastFlow := openoltpb2.Flow{
2579 FlowId: flowID,
2580 FlowType: Multicast,
2581 NetworkIntfId: int32(networkInterfaceID),
2582 GroupId: groupID,
2583 Classifier: classifierProto,
2584 Priority: int32(flow.Priority),
2585 Cookie: flow.Cookie}
2586
Kent Hagermane6ff1012020-07-14 15:07:53 -04002587 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002588 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002589 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002590 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002591 //get cached group
Kent Hagermane6ff1012020-07-14 15:07:53 -04002592 if group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002593 //calling groupAdd to set group members after multicast flow creation
Kent Hagermane6ff1012020-07-14 15:07:53 -04002594 if err := f.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002595 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002596 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002597 //cached group can be removed now
2598 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2599 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2600 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002601 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002602
2603 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2604 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2605 int32(onuID),
2606 int32(uniID),
2607 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002608 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002609 }
2610 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002611}
2612
Esin Karaman65409d82020-03-18 10:58:18 +00002613//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2614func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2615 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002616 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002617 if err != nil {
2618 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2619 }
2620 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002621 }
Esin Karaman65409d82020-03-18 10:58:18 +00002622 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302623 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002624 if e == nil && len(nniPorts) > 0 {
2625 return nniPorts[0], nil
2626 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302627 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002628}
2629
2630// AddGroup add or update the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002631func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002632 logger.Infow(ctx, "add-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002633 if group == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002634 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002635 }
2636
2637 groupToOlt := openoltpb2.Group{
2638 GroupId: group.Desc.GroupId,
2639 Command: openoltpb2.Group_SET_MEMBERS,
2640 Action: f.buildGroupAction(),
2641 }
2642
Neha Sharma96b7bf22020-06-15 10:37:32 +00002643 logger.Debugw(ctx, "sending-group-to-device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05302644 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002645 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002646 return olterrors.NewErrAdapter("add-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002647 }
2648 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05302649 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002650 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002651 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002652 logger.Infow(ctx, "add-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002653 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002654}
2655
Esin Karamand519bbf2020-07-01 11:16:03 +00002656// DeleteGroup deletes a group from the device
2657func (f *OpenOltFlowMgr) DeleteGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
2658 logger.Debugw(ctx, "delete-group", log.Fields{"group": group})
2659 if group == nil {
2660 logger.Error(ctx, "unable-to-delete-group--invalid-argument--group-is-nil")
2661 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
2662 }
2663
2664 groupToOlt := openoltpb2.Group{
2665 GroupId: group.Desc.GroupId,
2666 }
2667
2668 logger.Debugw(ctx, "deleting-group-from-device", log.Fields{"groupToOlt": groupToOlt})
2669 _, err := f.deviceHandler.Client.DeleteGroup(ctx, &groupToOlt)
2670 if err != nil {
2671 logger.Errorw(ctx, "delete-group-failed-on-dev", log.Fields{"groupToOlt": groupToOlt, "err": err})
2672 return olterrors.NewErrAdapter("delete-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
2673 }
2674 //remove group from the store
2675 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, group.Desc.GroupId, false); err != nil {
2676 return olterrors.NewErrPersistence("delete", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
2677 }
2678 logger.Debugw(ctx, "delete-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
2679 return nil
2680}
2681
Esin Karamanccb714b2019-11-29 15:02:06 +00002682//buildGroupAction creates and returns a group action
2683func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2684 var actionCmd openoltpb2.ActionCmd
2685 var action openoltpb2.Action
2686 action.Cmd = &actionCmd
2687 //pop outer vlan
2688 action.Cmd.RemoveOuterTag = true
2689 return &action
2690}
2691
2692// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002693func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002694 logger.Infow(ctx, "modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002695 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002696 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002697 }
2698
Neha Sharma96b7bf22020-06-15 10:37:32 +00002699 newGroup := f.buildGroup(ctx, group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002700 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302701 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002702
2703 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002704 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002705 }
2706
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002707 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002708 if groupExists {
2709 // group already exists
Neha Sharma96b7bf22020-06-15 10:37:32 +00002710 current = f.buildGroup(ctx, group.Desc.GroupId, val.Desc.GetBuckets())
2711 logger.Debugw(ctx, "modify-group--group exists",
Shrey Baid26912972020-04-16 21:02:31 +05302712 log.Fields{
2713 "group on the device": val,
2714 "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002715 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002716 current = f.buildGroup(ctx, group.Desc.GroupId, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002717 }
2718
Neha Sharma96b7bf22020-06-15 10:37:32 +00002719 logger.Debugw(ctx, "modify-group--comparing-current-and-new",
Shrey Baid26912972020-04-16 21:02:31 +05302720 log.Fields{
2721 "group on the device": current,
2722 "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002723 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002724 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002725 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002726 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002727
Neha Sharma96b7bf22020-06-15 10:37:32 +00002728 logger.Infow(ctx, "modify-group--differences found", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302729 "membersToBeAdded": membersToBeAdded,
2730 "membersToBeRemoved": membersToBeRemoved,
2731 "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002732
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002733 groupToOlt := openoltpb2.Group{
2734 GroupId: group.Desc.GroupId,
2735 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002736 var errAdd, errRemoved error
Kent Hagermane6ff1012020-07-14 15:07:53 -04002737 if len(membersToBeAdded) > 0 {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002738 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2739 groupToOlt.Members = membersToBeAdded
2740 //execute addMembers
Neha Sharma96b7bf22020-06-15 10:37:32 +00002741 errAdd = f.callGroupAddRemove(ctx, &groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002742 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002743 if len(membersToBeRemoved) > 0 {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002744 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2745 groupToOlt.Members = membersToBeRemoved
2746 //execute removeMembers
Neha Sharma96b7bf22020-06-15 10:37:32 +00002747 errRemoved = f.callGroupAddRemove(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002748 }
2749
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002750 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002751 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302752 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002753 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002754 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002755 logger.Infow(ctx, "modify-group-was-success--storing-group",
Shrey Baid26912972020-04-16 21:02:31 +05302756 log.Fields{
2757 "group": group,
2758 "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002759 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002760 logger.Warnw(ctx, "one-of-the-group-add/remove-operations-failed--cannot-save-group-modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002761 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002762 if errAdd != nil {
2763 return errAdd
2764 }
2765 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002766 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002767 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002768}
2769
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002770//callGroupAddRemove performs add/remove buckets operation for the indicated group
Neha Sharma96b7bf22020-06-15 10:37:32 +00002771func (f *OpenOltFlowMgr) callGroupAddRemove(ctx context.Context, group *openoltpb2.Group) error {
2772 if err := f.performGroupOperation(ctx, group); err != nil {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002773 st, _ := status.FromError(err)
2774 //ignore already exists error code
2775 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002776 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002777 }
2778 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002779 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002780}
2781
2782//findDiff compares group members and finds members which only exists in groups2
2783func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2784 var members []*openoltpb2.GroupMember
2785 for _, bucket := range group2.Members {
2786 if !f.contains(group1.Members, bucket) {
2787 // bucket does not exist and must be added
2788 members = append(members, bucket)
2789 }
2790 }
2791 return members
2792}
2793
2794//contains returns true if the members list contains the given member; false otherwise
2795func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2796 for _, groupMember := range members {
2797 if groupMember.InterfaceId == member.InterfaceId {
2798 return true
2799 }
2800 }
2801 return false
2802}
2803
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002804//performGroupOperation call performGroupOperation operation of openolt proto
Neha Sharma96b7bf22020-06-15 10:37:32 +00002805func (f *OpenOltFlowMgr) performGroupOperation(ctx context.Context, group *openoltpb2.Group) error {
2806 logger.Debugw(ctx, "sending-group-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05302807 log.Fields{
2808 "groupToOlt": group,
2809 "command": group.Command})
Esin Karamanccb714b2019-11-29 15:02:06 +00002810 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2811 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002812 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002813 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002814 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002815}
2816
2817//buildGroup build openoltpb2.Group from given group id and bucket list
Neha Sharma96b7bf22020-06-15 10:37:32 +00002818func (f *OpenOltFlowMgr) buildGroup(ctx context.Context, groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
Esin Karamanccb714b2019-11-29 15:02:06 +00002819 group := openoltpb2.Group{
2820 GroupId: groupID}
2821 // create members of the group
Kent Hagermane6ff1012020-07-14 15:07:53 -04002822 for _, ofBucket := range buckets {
2823 member := f.buildMember(ctx, ofBucket)
2824 if member != nil && !f.contains(group.Members, member) {
2825 group.Members = append(group.Members, member)
Esin Karamanccb714b2019-11-29 15:02:06 +00002826 }
2827 }
2828 return &group
2829}
2830
2831//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
Neha Sharma96b7bf22020-06-15 10:37:32 +00002832func (f *OpenOltFlowMgr) buildMember(ctx context.Context, ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
Esin Karamanccb714b2019-11-29 15:02:06 +00002833 var outPort uint32
2834 outPortFound := false
2835 for _, ofAction := range ofBucket.Actions {
2836 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2837 outPort = ofAction.GetOutput().Port
2838 outPortFound = true
2839 }
2840 }
2841
2842 if !outPortFound {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002843 logger.Debugw(ctx, "bucket-skipped-since-no-out-port-found-in-it", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002844 return nil
2845 }
2846 interfaceID := IntfIDFromUniPortNum(outPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002847 logger.Debugw(ctx, "got-associated-interface-id-of-the-port",
Shrey Baid26912972020-04-16 21:02:31 +05302848 log.Fields{
2849 "portNumber:": outPort,
2850 "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002851 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2852 member := openoltpb2.GroupMember{
2853 InterfaceId: interfaceID,
2854 InterfaceType: openoltpb2.GroupMember_PON,
2855 GemPortId: groupInfo.gemPortID,
2856 Priority: groupInfo.servicePriority,
2857 }
2858 //add member to the group
2859 return &member
2860 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002861 logger.Warnf(ctx, "bucket-skipped-since-interface-2-gem-mapping-cannot-be-found", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002862 return nil
2863}
2864
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002865//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002866func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002867
Neha Sharma96b7bf22020-06-15 10:37:32 +00002868 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302869 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002870 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302871 log.Fields{
2872 "intf-id": intfID,
2873 "onu-id": onuID,
2874 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002875 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302876 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002877 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002878
Neha Sharma96b7bf22020-06-15 10:37:32 +00002879 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002880 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002881 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
manikkaraj k17652a72019-05-06 09:06:36 -04002882 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2883 tpDownloadMsg,
2884 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302885 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002886 onuDev.deviceType,
2887 onuDev.deviceID,
2888 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002889 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302890 return olterrors.NewErrCommunication("send-techprofile-download-request",
2891 log.Fields{
2892 "from-adapter": f.deviceHandler.device.Type,
2893 "to-adapter": onuDev.deviceType,
2894 "onu-id": onuDev.deviceID,
2895 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002896 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002897 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302898 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302899}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002900
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302901//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002902func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302903
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002904 f.onuGemInfoLock.Lock()
2905 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002906
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302907 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2908 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002909 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002910 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302911 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002912 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302913 log.Fields{
2914 "intf-id": intfID,
2915 "onu-id": onuID,
2916 "serial-num": serialNum,
2917 "onu": onu,
2918 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002919 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002920}
2921
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302922//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302923func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002924
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002925 f.onuGemInfoLock.Lock()
2926 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002927
Neha Sharma96b7bf22020-06-15 10:37:32 +00002928 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302929 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002930 "gem-port-id": gemPort,
2931 "intf-id": intfID,
2932 "onu-id": onuID,
2933 "device-id": f.deviceHandler.device.Id,
2934 "onu-gem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302935 onugem := f.onuGemInfo[intfID]
2936 // update the gem to the local cache as well as to kv strore
2937 for idx, onu := range onugem {
2938 if onu.OnuID == onuID {
2939 // check if gem already exists , else update the cache and kvstore
2940 for _, gem := range onu.GemPorts {
2941 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002942 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302943 log.Fields{
2944 "gem": gemPort,
2945 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302946 return
2947 }
2948 }
2949 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2950 f.onuGemInfo[intfID] = onugem
2951 }
2952 }
npujarec5762e2020-01-01 14:08:48 +05302953 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302954 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002955 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302956 log.Fields{
2957 "intf-id": intfID,
2958 "onu-id": onuID,
2959 "gemPort": gemPort,
2960 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002961 return
2962 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002963 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302964 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002965 "gem-port-id": gemPort,
2966 "intf-id": intfID,
2967 "onu-id": onuID,
2968 "device-id": f.deviceHandler.device.Id,
2969 "onu-gem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002970}
2971
2972// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002973
2974//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002975func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302976
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002977 f.onuGemInfoLock.RLock()
2978 defer f.onuGemInfoLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302979
Neha Sharma96b7bf22020-06-15 10:37:32 +00002980 logger.Infow(ctx, "getting-onu-id-from-gem-port-and-pon-port",
Shrey Baid26912972020-04-16 21:02:31 +05302981 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002982 "device-id": f.deviceHandler.device.Id,
2983 "onu-geminfo": f.onuGemInfo[intfID],
2984 "intf-id": intfID,
2985 "gemport-id": gemPortID})
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002986
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302987 // get onuid from the onugem info cache
2988 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002989
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302990 for _, onu := range onugem {
2991 for _, gem := range onu.GemPorts {
2992 if gem == gemPortID {
2993 return onu.OnuID, nil
2994 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002995 }
2996 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002997 logger.Errorw(ctx, "onu-id-from-gem-port-not-found", log.Fields{
2998 "gem-port-id": gemPortID,
2999 "interface-id": intfID,
Kent Hagermane6ff1012020-07-14 15:07:53 -04003000 "all-gems-on-port": onugem,
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003001 })
Thomas Lee S94109f12020-03-03 16:39:29 +05303002 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003003 "interface-id": intfID,
3004 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00003005 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003006}
3007
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003008//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05303009func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003010 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003011 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003012 var err error
3013
3014 if packetIn.IntfType == "pon" {
3015 // packet indication does not have serial number , so sending as nil
Neha Sharma96b7bf22020-06-15 10:37:32 +00003016 if onuID, err = f.getOnuIDfromGemPortMap(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003017 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003018 return logicalPortNum, err
3019 }
3020 if packetIn.PortNo != 0 {
3021 logicalPortNum = packetIn.PortNo
3022 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003023 uniID := uint32(0) // FIXME - multi-uni support
Neha Sharma96b7bf22020-06-15 10:37:32 +00003024 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003025 }
3026 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
Esin Karaman7fb80c22020-07-16 14:23:33 +00003027 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003028 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003029 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003030 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003031 logger.Infow(ctx, "retrieved-logicalport-from-packet-in",
Shrey Baid26912972020-04-16 21:02:31 +05303032 log.Fields{
3033 "logical-port-num": logicalPortNum,
3034 "intf-type": packetIn.IntfType,
3035 "packet": hex.EncodeToString(packetIn.Pkt),
3036 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003037 return logicalPortNum, nil
3038}
3039
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003040//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00003041func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003042 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00003043
3044 ctag, priority, err := getCTagFromPacket(ctx, packet)
3045 if err != nil {
3046 return 0, err
3047 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303048
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003049 f.onuGemInfoLock.RLock()
3050 defer f.onuGemInfoLock.RUnlock()
Esin Karaman7fb80c22020-07-16 14:23:33 +00003051 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003052 var ok bool
3053 gemPortID, ok = f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303054 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003055 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05303056 log.Fields{
3057 "pktinkey": pktInkey,
3058 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003059
3060 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003061 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303062 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003063 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303064 if err == nil {
3065 if gemPortID != 0 {
3066 f.packetInGemPort[pktInkey] = gemPortID
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05303068 log.Fields{
3069 "pktinkey": pktInkey,
3070 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303071 return gemPortID, nil
3072 }
3073 }
Shrey Baid26912972020-04-16 21:02:31 +05303074 return uint32(0), olterrors.NewErrNotFound("gem-port",
3075 log.Fields{
3076 "pktinkey": pktInkey,
3077 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003078
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003079}
3080
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003081// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303082func installFlowOnAllGemports(ctx context.Context,
3083 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003084 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003085 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05303086 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303087 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303088 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003089 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003090 args map[string]uint32,
3091 classifier map[string]interface{}, action map[string]interface{},
3092 logicalFlow *ofp.OfpFlowStats,
3093 gemPorts []uint32,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003094 TpInst interface{},
Manikkaraj kb1d51442019-07-23 10:41:02 -04003095 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00003096 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003097 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003098 vlanID ...uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003099 logger.Debugw(ctx, "installing-flow-on-all-gem-ports",
Shrey Baid26912972020-04-16 21:02:31 +05303100 log.Fields{
3101 "FlowType": FlowType,
3102 "gemPorts": gemPorts,
3103 "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05303104
Gamze Abaka724d0852020-03-18 12:10:24 +00003105 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
3106 // We need to trim prefix "0b", before further processing
3107 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
3108 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
3109
3110 // If a particular character in the string is set to '1', identify the index of this character from
3111 // the LSB position which marks the PCP bit consumed by the given gem port.
3112 // This PCP bit now becomes a classifier in the flow.
3113
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003114 switch TpInst := TpInst.(type) {
3115 case *tp.TechProfile:
3116 attributes := TpInst.DownstreamGemPortAttributeList
3117 if direction == Upstream {
3118 attributes = TpInst.UpstreamGemPortAttributeList
Gamze Abaka724d0852020-03-18 12:10:24 +00003119 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003120
3121 for _, gemPortAttribute := range attributes {
3122 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
3123 continue
Gamze Abaka724d0852020-03-18 12:10:24 +00003124 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003125 gemPortID := gemPortAttribute.GemportID
3126 if allPbitsMarked(gemPortAttribute.PbitMap) {
3127 classifier[VlanPcp] = uint32(VlanPCPMask)
3128 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003129 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3130 logger.Warn(ctx, err)
3131 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003132 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003133 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3134 logger.Warn(ctx, err)
3135 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003136 }
3137 } else {
3138 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
3139 if pbitSet == BinaryBit1 {
3140 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3141 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003142 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3143 logger.Warn(ctx, err)
3144 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003145 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003146 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3147 logger.Warn(ctx, err)
3148 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003149 }
3150 }
3151 }
3152 }
3153 }
3154 case *tp.EponProfile:
3155 if direction == Upstream {
3156 attributes := TpInst.UpstreamQueueAttributeList
3157 for _, queueAttribute := range attributes {
3158 gemPortID := queueAttribute.GemportID
3159 if allPbitsMarked(queueAttribute.PbitMap) {
3160 classifier[VlanPcp] = uint32(VlanPCPMask)
Gamze Abaka724d0852020-03-18 12:10:24 +00003161 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003162 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3163 logger.Warn(ctx, err)
3164 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003165 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003166 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3167 logger.Warn(ctx, err)
3168 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003169 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003170 } else {
3171 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3172 if pbitSet == BinaryBit1 {
3173 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3174 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003175 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3176 logger.Warn(ctx, err)
3177 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003178 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003179 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3180 logger.Warn(ctx, err)
3181 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003182 }
3183 }
3184 }
3185 }
3186 }
3187 } else {
3188 attributes := TpInst.DownstreamQueueAttributeList
3189 for _, queueAttribute := range attributes {
3190 gemPortID := queueAttribute.GemportID
3191 if allPbitsMarked(queueAttribute.PbitMap) {
3192 classifier[VlanPcp] = uint32(VlanPCPMask)
3193 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003194 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3195 logger.Warn(ctx, err)
3196 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003197 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003198 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3199 logger.Warn(ctx, err)
3200 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003201 }
3202 } else {
3203 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3204 if pbitSet == BinaryBit1 {
3205 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3206 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003207 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3208 logger.Warn(ctx, err)
3209 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003210 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003211 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3212 logger.Warn(ctx, err)
3213 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003214 }
3215 }
3216 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05303217 }
3218 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04003219 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003220 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003221 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpInst": TpInst})
Manikkaraj kb1d51442019-07-23 10:41:02 -04003222 }
3223}
3224
Gamze Abaka724d0852020-03-18 12:10:24 +00003225func allPbitsMarked(pbitMap string) bool {
3226 for pos, pBit := range pbitMap {
3227 if pos >= 2 && pBit != BinaryBit1 {
3228 return false
3229 }
3230 }
3231 return true
3232}
3233
David K. Bainbridge794735f2020-02-11 21:01:37 -08003234func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003235 logger.Debug(ctx, "adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003236 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003237 classifier[PacketTagType] = DoubleTag
3238 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003239 /* We manage flowId resource pool on per PON port basis.
3240 Since this situation is tricky, as a hack, we pass the NNI port
3241 index (network_intf_id) as PON port Index for the flowId resource
3242 pool. Also, there is no ONU Id available for trapping DHCP packets
3243 on NNI port, use onu_id as -1 (invalid)
3244 ****************** CAVEAT *******************
3245 This logic works if the NNI Port Id falls within the same valid
3246 range of PON Port Ids. If this doesn't work for some OLT Vendor
3247 we need to have a re-look at this.
3248 *********************************************
3249 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003250 onuID := -1
3251 uniID := -1
3252 gemPortID := -1
3253 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00003254 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303255 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303256 return olterrors.NewErrNotFound("nni-intreface-id",
3257 log.Fields{
3258 "classifier": classifier,
3259 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003260 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303261 }
3262
Neha Sharma96b7bf22020-06-15 10:37:32 +00003263 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303264 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003265 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003266 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003267 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003268 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003269 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303270 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id",
3271 log.Fields{
3272 "interface-id": networkInterfaceID,
3273 "onu-id": onuID,
3274 "uni-id": uniID,
3275 "gem-port-id": gemPortID,
3276 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003277 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003278 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003279 classifierProto, err := makeOpenOltClassifierField(classifier)
3280 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003281 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003282 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003283 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003284 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003285 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003286 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003287 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003288 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003289 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3290 OnuId: int32(onuID), // OnuId not required
3291 UniId: int32(uniID), // UniId not used
3292 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07003293 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003294 AllocId: int32(allocID), // AllocId not used
3295 NetworkIntfId: int32(networkInterfaceID),
3296 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003297 Classifier: classifierProto,
3298 Action: actionProto,
3299 Priority: int32(logicalFlow.Priority),
3300 Cookie: logicalFlow.Cookie,
3301 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003302 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003303 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003304 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003305 logger.Info(ctx, "dhcp-trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003306 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3307 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3308 int32(onuID),
3309 int32(uniID),
3310 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003311 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003312 }
3313 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003314}
salmansiddiqui7ac62132019-08-22 03:58:50 +00003315
Esin Karamanae41e2b2019-12-17 18:13:13 +00003316//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
3317func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
3318 var packetType string
3319 ovid, ivid := false, false
3320 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
3321 vid := vlanID & VlanvIDMask
3322 if vid != ReservedVlan {
3323 ovid = true
3324 }
3325 }
3326 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
3327 vid := uint32(metadata)
3328 if vid != ReservedVlan {
3329 ivid = true
3330 }
3331 }
3332 if ovid && ivid {
3333 packetType = DoubleTag
3334 } else if !ovid && !ivid {
3335 packetType = Untagged
3336 } else {
3337 packetType = SingleTag
3338 }
3339 return packetType
3340}
3341
3342//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08003343func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003344 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003345 action := make(map[string]interface{})
3346 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
3347 action[TrapToHost] = true
3348 /* We manage flowId resource pool on per PON port basis.
3349 Since this situation is tricky, as a hack, we pass the NNI port
3350 index (network_intf_id) as PON port Index for the flowId resource
3351 pool. Also, there is no ONU Id available for trapping packets
3352 on NNI port, use onu_id as -1 (invalid)
3353 ****************** CAVEAT *******************
3354 This logic works if the NNI Port Id falls within the same valid
3355 range of PON Port Ids. If this doesn't work for some OLT Vendor
3356 we need to have a re-look at this.
3357 *********************************************
3358 */
3359 onuID := -1
3360 uniID := -1
3361 gemPortID := -1
3362 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00003363 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003364 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303365 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003366 "classifier": classifier,
3367 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003368 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003369 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003370 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303371 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003372 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003373 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003374 }
npujarec5762e2020-01-01 14:08:48 +05303375 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003376 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303377 return olterrors.NewErrNotFound("igmp-flow-id",
3378 log.Fields{
3379 "interface-id": networkInterfaceID,
3380 "onu-id": onuID,
3381 "uni-id": uniID,
3382 "gem-port-id": gemPortID,
3383 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003384 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003385 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003386 classifierProto, err := makeOpenOltClassifierField(classifier)
3387 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003388 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003389 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003390 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003391 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003392 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003393 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003394 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003395 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003396 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3397 OnuId: int32(onuID), // OnuId not required
3398 UniId: int32(uniID), // UniId not used
3399 FlowId: flowID,
3400 FlowType: Downstream,
3401 AllocId: int32(allocID), // AllocId not used
3402 NetworkIntfId: int32(networkInterfaceID),
3403 GemportId: int32(gemPortID), // GemportId not used
3404 Classifier: classifierProto,
3405 Action: actionProto,
3406 Priority: int32(logicalFlow.Priority),
3407 Cookie: logicalFlow.Cookie,
3408 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003409 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003410 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003411 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003412 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003413 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3414 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3415 int32(onuID),
3416 int32(uniID),
3417 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003418 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003419 }
3420 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003421}
3422
salmansiddiqui7ac62132019-08-22 03:58:50 +00003423func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
3424 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05303425 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003426 }
3427 if Dir == tp_pb.Direction_UPSTREAM {
3428 return "upstream", nil
3429 } else if Dir == tp_pb.Direction_DOWNSTREAM {
3430 return "downstream", nil
3431 }
3432 return "", nil
3433}
3434
Kent Hagermane6ff1012020-07-14 15:07:53 -04003435// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303436func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003437 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003438 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00003439 var gemPort uint32
3440 intfID := args[IntfID]
3441 onuID := args[OnuID]
3442 uniID := args[UniID]
3443 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003444 allocID := args[AllocID]
salmansiddiqui7ac62132019-08-22 03:58:50 +00003445 if ipProto, ok := classifierInfo[IPProto]; ok {
3446 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003447 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003448 "tp-id": tpID,
3449 "alloc-id": allocID,
3450 "intf-id": intfID,
3451 "onu-id": onuID,
3452 "uni-id": uniID,
3453 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003454 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003455 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003456 tp_pb.Direction_UPSTREAM,
3457 pcp.(uint32))
3458 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00003459
Kent Hagermane6ff1012020-07-14 15:07:53 -04003460 if err := f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3461 logger.Warn(ctx, err)
3462 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003463 } else {
3464 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003465 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003466 }
3467
Girish Gowdra32625212020-04-29 11:26:35 -07003468 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003469 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05303470 log.Fields{
3471 "intf-id": intfID,
3472 "onu-id": onuID,
3473 "uni-id": uniID,
3474 "classifier-info:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003475 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003476 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
Esin Karamanae41e2b2019-12-17 18:13:13 +00003477 tp_pb.Direction_UPSTREAM,
3478 pcp.(uint32))
Kent Hagermane6ff1012020-07-14 15:07:53 -04003479 if err := f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3480 logger.Warn(ctx, err)
3481 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00003482 } else {
3483 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003484 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003485 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003486 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003487 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003488 return
3489 }
3490 } else if ethType, ok := classifierInfo[EthType]; ok {
3491 if ethType.(uint32) == EapEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003492 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003493 "intf-id": intfID,
3494 "onu-id": onuID,
3495 "uni-id": uniID,
3496 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003497 var vlanID uint32
3498 if val, ok := classifierInfo[VlanVid]; ok {
3499 vlanID = (val.(uint32)) & VlanvIDMask
3500 } else {
3501 vlanID = DefaultMgmtVlan
3502 }
3503 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003504 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003505 tp_pb.Direction_UPSTREAM,
3506 pcp.(uint32))
3507
Kent Hagermane6ff1012020-07-14 15:07:53 -04003508 if err := f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID); err != nil {
3509 logger.Warn(ctx, err)
3510 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003511 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003512 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003513 }
3514 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003515 } else if _, ok := actionInfo[PushVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003516 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003517 "intf-id": intfID,
3518 "onu-id": onuID,
3519 "uni-id": uniID,
3520 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003521 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003522 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003523 tp_pb.Direction_UPSTREAM,
3524 pcp.(uint32))
3525 //Adding HSIA upstream flow
Kent Hagermane6ff1012020-07-14 15:07:53 -04003526 if err := f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3527 logger.Warn(ctx, err)
3528 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003529 } else {
3530 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003531 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003532 }
3533 } else if _, ok := actionInfo[PopVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003534 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003535 "intf-id": intfID,
3536 "onu-id": onuID,
3537 "uni-id": uniID,
3538 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003539 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003540 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05003541 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003542 pcp.(uint32))
3543 //Adding HSIA downstream flow
Kent Hagermane6ff1012020-07-14 15:07:53 -04003544 if err := f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3545 logger.Warn(ctx, err)
3546 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003547 } else {
3548 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003549 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003550 }
3551 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003552 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05303553 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003554 "intf-id": intfID,
3555 "onu-id": onuID,
3556 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05303557 "classifier": classifierInfo,
3558 "action": actionInfo,
3559 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003560 return
3561 }
3562 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04003563 go func() {
3564 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
3565 logger.Warn(ctx, err)
3566 }
3567 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003568}
3569
Gamze Abakafee36392019-10-03 11:17:24 +00003570func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
3571 flowIDList := f.flowsUsedByGemPort[gemPK]
Kent Hagermane6ff1012020-07-14 15:07:53 -04003572 return len(flowIDList) > 1
Gamze Abakafee36392019-10-03 11:17:24 +00003573}
3574
npujarec5762e2020-01-01 14:08:48 +05303575func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3576 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003577 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3578 for _, currentGemPort := range currentGemPorts {
3579 for _, tpGemPort := range tpGemPorts {
3580 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3581 return true, currentGemPort
3582 }
3583 }
3584 }
Girish Gowdra54934262019-11-13 14:19:55 +05303585 if tpInst.InstanceCtrl.Onu == "single-instance" {
3586 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Kent Hagermane6ff1012020-07-14 15:07:53 -04003587 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID); err != nil {
3588 logger.Warn(ctx, err)
3589 }
3590 if err := f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
3591 logger.Warn(ctx, err)
3592 }
Girish Gowdra54934262019-11-13 14:19:55 +05303593
3594 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3595 // still be used on other uni ports.
3596 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3597 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003598 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003599 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303600 for i := 0; i < len(tpInstances); i++ {
3601 tpI := tpInstances[i]
3602 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303603 for _, tpGemPort := range tpGemPorts {
3604 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003605 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303606 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303607 }
3608 }
3609 }
3610 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003611 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003612 return false, 0
3613}
3614
Neha Sharma96b7bf22020-06-15 10:37:32 +00003615func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003616 for _, field := range flows.GetOfbFields(flow) {
3617 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003618 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003619 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003620 } else if field.Type == flows.ETH_DST {
3621 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003622 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003623 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003624 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003625 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003626 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003627 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003628 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003629 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303630 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003631 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003632 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003633 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003634 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003635 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003636 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003637 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003638 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003639 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003640 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003641 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003642 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003643 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003644 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003645 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003646 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003647 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003648 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003649 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003650 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003651 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003652 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003653 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003654 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003655 return
3656 }
3657 }
3658}
3659
Neha Sharma96b7bf22020-06-15 10:37:32 +00003660func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003661 for _, action := range flows.GetActions(flow) {
3662 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003663 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003664 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003665 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003666 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003667 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003668 }
Scott Baker355d1742019-10-24 10:57:52 -07003669 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003670 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003671 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003672 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003673 if out := action.GetPush(); out != nil {
3674 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003675 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003676 } else {
3677 actionInfo[PushVlan] = true
3678 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003679 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303680 log.Fields{
3681 "push-tpid": actionInfo[TPID].(uint32),
3682 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003683 }
3684 }
Scott Baker355d1742019-10-24 10:57:52 -07003685 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003686 if out := action.GetSetField(); out != nil {
3687 if field := out.GetField(); field != nil {
3688 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003689 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003690 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003691 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3692 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003693 }
3694 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003695 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003696 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003697 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003698 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003699 }
3700 }
3701 return nil
3702}
3703
Neha Sharma96b7bf22020-06-15 10:37:32 +00003704func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003705 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003706 fieldtype := ofbField.GetType()
3707 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003708 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3709 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003710 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003711 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003712 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003713 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003714 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3715 pcp := ofbField.GetVlanPcp()
3716 actionInfo[VlanPcp] = pcp
3717 log.Debugw("action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003718 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003719 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003720 }
3721 }
3722}
3723
Neha Sharma96b7bf22020-06-15 10:37:32 +00003724func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003725 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003726 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003727 } else {
3728 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003729 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003730 }
3731}
3732
Neha Sharma96b7bf22020-06-15 10:37:32 +00003733func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003734 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003735 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003736 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3737 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003738 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003739 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003740 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303741 log.Fields{
3742 "newinport": classifierInfo[InPort].(uint32),
3743 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003744 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303745 return olterrors.NewErrNotFound("child-in-port",
3746 log.Fields{
3747 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3748 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003749 }
3750 }
3751 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003752 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003753 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003754 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003755 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003756 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003757 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303758 log.Fields{
3759 "newoutport": actionInfo[Output].(uint32),
3760 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003761 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303762 return olterrors.NewErrNotFound("out-port",
3763 log.Fields{
3764 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3765 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003766 }
3767 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3768 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003769 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003770 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003771 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303772 log.Fields{
3773 "newinport": actionInfo[Output].(uint32),
3774 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003775 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303776 return olterrors.NewErrNotFound("nni-port",
3777 log.Fields{
3778 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3779 "in-port": classifierInfo[InPort].(uint32),
3780 "out-port": actionInfo[Output].(uint32),
3781 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003782 }
3783 }
3784 }
3785 return nil
3786}
Gamze Abakafee36392019-10-03 11:17:24 +00003787
Neha Sharma96b7bf22020-06-15 10:37:32 +00003788func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003789 /* Metadata 8 bytes:
3790 Most Significant 2 Bytes = Inner VLAN
3791 Next 2 Bytes = Tech Profile ID(TPID)
3792 Least Significant 4 Bytes = Port ID
3793 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3794 subscriber related flows.
3795 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003796 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003797 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003798 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003799 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003800 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003801 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003802}
3803
3804func appendUnique(slice []uint32, item uint32) []uint32 {
3805 for _, sliceElement := range slice {
3806 if sliceElement == item {
3807 return slice
3808 }
3809 }
3810 return append(slice, item)
3811}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303812
3813// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003814func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303815
3816 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3817 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003818 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003819 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003820 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003821 log.Fields{
3822 "port-number": action[Output].(uint32),
3823 "error": err})
3824 return uint32(0), err
3825 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003826 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303827 return intfID, nil
3828 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003829 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003830 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003831 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003832 log.Fields{
3833 "port-number": action[Output].(uint32),
3834 "error": err})
3835 return uint32(0), err
3836 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003837 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303838 return intfID, nil
3839 }
3840 return uint32(0), nil
3841}
3842
3843// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003844func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3845 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3846 if err != nil {
3847 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3848 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3849 return
3850 }
3851 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003852
3853 f.onuGemInfoLock.Lock()
3854 defer f.onuGemInfoLock.Unlock()
3855
Matt Jeanneret1719a072019-12-20 14:50:14 -05003856 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303857 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003858 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003859 logger.Infow(ctx, "pktin-key/value-found-in-cache--no-need-to-update-kv--assume-both-in-sync",
Shrey Baid26912972020-04-16 21:02:31 +05303860 log.Fields{
3861 "pktinkey": pktInkey,
3862 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003863 return
3864 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303865 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003866 f.packetInGemPort[pktInkey] = gemPort
3867
npujarec5762e2020-01-01 14:08:48 +05303868 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003869 logger.Infow(ctx, "pktin-key-not-found-in-local-cache-value-is-different--updating-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05303870 log.Fields{
3871 "pktinkey": pktInkey,
3872 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303873}
3874
Esin Karaman7fb80c22020-07-16 14:23:33 +00003875//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3876func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3877 if packet == nil || len(packet) < 18 {
3878 log.Error("unable-get-c-tag-from-the-packet--invalid-packet-length ")
3879 return 0, 0, errors.New("invalid packet length")
3880 }
3881 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3882 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3883
3884 var index int8
3885 if outerEthType == 0x8100 {
3886 if innerEthType == 0x8100 {
3887 // q-in-q 802.1ad or 802.1q double tagged packet.
3888 // get the inner vlanId
3889 index = 18
3890 } else {
3891 index = 14
3892 }
3893 priority := (packet[index] >> 5) & 0x7
3894 //13 bits composes vlanId value
3895 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3896 return vlan, priority, nil
3897 }
3898 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3899 return 0, 0, nil
3900}
3901
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303902// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303903func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003904
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003905 f.onuGemInfoLock.Lock()
3906 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003907
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303908 onugem := f.onuGemInfo[intfID]
3909 for idx, onu := range onugem {
3910 if onu.OnuID == onuID {
3911 for _, uni := range onu.UniPorts {
3912 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003913 logger.Infow(ctx, "uni-already-in-cache--no-need-to-update-cache-and-kv-store", log.Fields{"uni": portNum})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303914 return
3915 }
3916 }
3917 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3918 f.onuGemInfo[intfID] = onugem
3919 }
3920 }
npujarec5762e2020-01-01 14:08:48 +05303921 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003922
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303923}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303924
npujarec5762e2020-01-01 14:08:48 +05303925func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3926 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303927 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003928 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303929 return
3930 }
3931 for gem, FlowIDs := range flowIDsList {
3932 gemPK := gemPortKey{intf, uint32(gem)}
3933 f.flowsUsedByGemPort[gemPK] = FlowIDs
3934 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303935}
Esin Karamanccb714b2019-11-29 15:02:06 +00003936
3937//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
3938//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05303939func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
3940 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00003941 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003942 logger.Error(ctx, "failed-to-get-pon-interface-to-multicast-queue-map")
Esin Karamanccb714b2019-11-29 15:02:06 +00003943 return
3944 }
3945 for intf, queueInfo := range storedMulticastQueueMap {
3946 q := queueInfoBrief{
3947 gemPortID: queueInfo[0],
3948 servicePriority: queueInfo[1],
3949 }
3950 f.interfaceToMcastQueueMap[intf] = &q
3951 }
3952}
3953
3954//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
3955//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
3956//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05303957func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
3958 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00003959 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003960 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00003961 }
3962 if exists {
3963 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
3964 }
3965 return nil, exists, nil
3966}
3967
3968func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
3969 groupDesc := ofp.OfpGroupDesc{
3970 Type: ofp.OfpGroupType_OFPGT_ALL,
3971 GroupId: groupID,
3972 }
3973 groupEntry := ofp.OfpGroupEntry{
3974 Desc: &groupDesc,
3975 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003976 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003977 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00003978 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003979 bucket := ofp.OfpBucket{
3980 Actions: acts,
3981 }
3982 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00003983 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003984 return &groupEntry
3985}