blob: 3d928c4ac3ce6209ed791c83e89aea799fdfeb24 [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
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301069
Neha Sharma96b7bf22020-06-15 10:37:32 +00001070 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301071 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001072 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301073 log.Fields{
1074 "device-id": f.deviceHandler.device.Id,
1075 "intf-id": intfID,
1076 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001077 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301078 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301079
David K. Bainbridge794735f2020-02-11 21:01:37 -08001080 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 +05301081
1082 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301083 return olterrors.NewErrNotFound("flow",
1084 log.Fields{
1085 "interface-id": intfID,
1086 "gem-port": gemPortID,
1087 "cookie": flowStoreCookie,
1088 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001089 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301090 }
1091
Neha Sharma96b7bf22020-06-15 10:37:32 +00001092 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301093 log.Fields{
1094 "ul_classifier": classifier,
1095 "ul_action": action,
1096 "uplinkFlowId": flowID,
1097 "intf-id": intfID,
1098 "onu-id": onuID,
1099 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301100
David K. Bainbridge794735f2020-02-11 21:01:37 -08001101 classifierProto, err := makeOpenOltClassifierField(classifier)
1102 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301103 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301104 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001105 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001106 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001107 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301108 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301109 }
1110
David K. Bainbridge794735f2020-02-11 21:01:37 -08001111 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001112 OnuId: int32(onuID),
1113 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301114 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001115 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001116 AllocId: int32(allocID),
1117 NetworkIntfId: int32(networkIntfID),
1118 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301119 Classifier: classifierProto,
1120 Action: actionProto,
1121 Priority: int32(logicalFlow.Priority),
1122 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001123 PortNo: portNo,
1124 TechProfileId: tpID,
1125 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001126 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301127 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001128 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001129 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301130 log.Fields{
1131 "device-id": f.deviceHandler.device.Id,
1132 "flow-id": flowID,
1133 "intf-id": intfID,
1134 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001135 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
1136 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
1137 dhcpFlow.OnuId,
1138 dhcpFlow.UniId,
1139 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301140 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1141 log.Fields{
1142 "flow": dhcpFlow,
1143 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301144 }
1145
David K. Bainbridge794735f2020-02-11 21:01:37 -08001146 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301147}
1148
Esin Karamanae41e2b2019-12-17 18:13:13 +00001149//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301150func (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 +00001151 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32) error {
1152 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001153}
1154
1155//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301156func (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 +00001157 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string, tpID uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001158
Neha Sharma96b7bf22020-06-15 10:37:32 +00001159 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001160 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301161 return olterrors.NewErrNotFound("nni-interface-id",
1162 log.Fields{
1163 "classifier": classifier,
1164 "action": action,
1165 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001166 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001167 }
1168
1169 // Clear the action map
1170 for k := range action {
1171 delete(action, k)
1172 }
1173
1174 action[TrapToHost] = true
1175 classifier[PacketTagType] = SingleTag
1176 delete(classifier, VlanVid)
1177
Neha Sharma96b7bf22020-06-15 10:37:32 +00001178 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301179 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001180 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001181 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001182 }
1183
npujarec5762e2020-01-01 14:08:48 +05301184 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 +00001185
1186 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301187 return olterrors.NewErrNotFound("flow-id",
1188 log.Fields{
1189 "intf-id": intfID,
1190 "oni-id": onuID,
1191 "cookie": flowStoreCookie,
1192 "flow-type": flowType,
1193 "device-id": f.deviceHandler.device.Id,
1194 "onu-id": onuID},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001195 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001196 }
1197
Neha Sharma96b7bf22020-06-15 10:37:32 +00001198 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301199 log.Fields{
1200 "ul_classifier": classifier,
1201 "ul_action": action,
1202 "uplinkFlowId": flowID,
1203 "flowType": flowType,
1204 "device-id": f.deviceHandler.device.Id,
1205 "intf-id": intfID,
1206 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001207
David K. Bainbridge794735f2020-02-11 21:01:37 -08001208 classifierProto, err := makeOpenOltClassifierField(classifier)
1209 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301210 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001211 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001212 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301213 log.Fields{
1214 "classifier": *classifierProto,
1215 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001216 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001217 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301218 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001219 }
1220
David K. Bainbridge794735f2020-02-11 21:01:37 -08001221 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001222 OnuId: int32(onuID),
1223 UniId: int32(uniID),
1224 FlowId: flowID,
1225 FlowType: Upstream,
1226 AllocId: int32(allocID),
1227 NetworkIntfId: int32(networkIntfID),
1228 GemportId: int32(gemPortID),
1229 Classifier: classifierProto,
1230 Action: actionProto,
1231 Priority: int32(logicalFlow.Priority),
1232 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001233 PortNo: portNo,
1234 TechProfileId: tpID,
1235 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001236
David K. Bainbridge794735f2020-02-11 21:01:37 -08001237 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301238 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 -08001239 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001240 logger.Infof(ctx, "%s ul-flow-added-to-device-successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001241
David K. Bainbridge794735f2020-02-11 21:01:37 -08001242 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
1243 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1244 flow.OnuId,
1245 flow.UniId,
1246 flow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301247 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 +00001248 }
1249
David K. Bainbridge794735f2020-02-11 21:01:37 -08001250 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001251}
1252
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001253// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001254func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1255 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1256 gemPortID uint32, vlanID uint32, tpID uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001257 logger.Infow(ctx, "adding-eapol-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301258 log.Fields{
1259 "intf-id": intfID,
1260 "onu-id": onuID,
1261 "port-no": portNo,
1262 "alloc-id": allocID,
1263 "gemport-id": gemPortID,
1264 "vlan-id": vlanID,
1265 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301266
1267 uplinkClassifier := make(map[string]interface{})
1268 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301269
manikkaraj kbf256be2019-03-25 00:13:48 +05301270 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001271 uplinkClassifier[EthType] = uint32(EapEthType)
1272 uplinkClassifier[PacketTagType] = SingleTag
1273 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001274 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301275 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001276 uplinkAction[TrapToHost] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00001277 flowStoreCookie := getFlowStoreCookie(ctx, uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301278 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001279 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301280 "device-id": f.deviceHandler.device.Id,
1281 "onu-id": onuID,
1282 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001283 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301284 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301285 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +00001286 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +05301287 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301288 return olterrors.NewErrNotFound("flow-id",
1289 log.Fields{
1290 "intf-id": intfID,
1291 "onu-id": onuID,
1292 "coookie": flowStoreCookie,
1293 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001294 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301295 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001296 logger.Debugw(ctx, "creating-ul-eapol-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301297 log.Fields{
1298 "ul_classifier": uplinkClassifier,
1299 "ul_action": uplinkAction,
1300 "uplinkFlowId": uplinkFlowID,
1301 "device-id": f.deviceHandler.device.Id,
1302 "intf-id": intfID,
1303 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301304
David K. Bainbridge794735f2020-02-11 21:01:37 -08001305 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1306 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301307 return olterrors.NewErrInvalidValue(log.Fields{
1308 "classifier": uplinkClassifier,
1309 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301310 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001311 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301312 log.Fields{
1313 "classifier": *classifierProto,
1314 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001315 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001316 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301317 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301318 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001319 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301320 log.Fields{
1321 "action": *actionProto,
1322 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001323 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301324 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301325 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001326 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301327 "action": action,
1328 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001329 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301330 }
1331
David K. Bainbridge794735f2020-02-11 21:01:37 -08001332 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001333 OnuId: int32(onuID),
1334 UniId: int32(uniID),
1335 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001336 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001337 AllocId: int32(allocID),
1338 NetworkIntfId: int32(networkIntfID),
1339 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301340 Classifier: classifierProto,
1341 Action: actionProto,
1342 Priority: int32(logicalFlow.Priority),
1343 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001344 PortNo: portNo,
1345 TechProfileId: tpID,
1346 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001347 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301348 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001349 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001350 logger.Infow(ctx, "eapol-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301351 log.Fields{
1352 "device-id": f.deviceHandler.device.Id,
1353 "onu-id": onuID,
1354 "intf-id": intfID,
1355 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001356 flowCategory := "EAPOL"
1357 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1358 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1359 upstreamFlow.OnuId,
1360 upstreamFlow.UniId,
1361 upstreamFlow.FlowId,
1362 /* lowCategory, */
1363 flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301364 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1365 log.Fields{
1366 "flow": upstreamFlow,
1367 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301368 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001369 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301370}
1371
David K. Bainbridge794735f2020-02-11 21:01:37 -08001372func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001373 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001374
1375 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1376 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1377 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001378 if vlanID != ReservedVlan {
1379 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001380 classifier.OVid = vid
1381 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301382 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001383 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1384 vid := uint32(metadata)
1385 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001386 classifier.IVid = vid
1387 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301388 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301389 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001390 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301391 classifier.OPbits = vlanPcp
1392 } else {
1393 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301394 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001395 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1396 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1397 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1398 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001399 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001400 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1401 classifier.PktTagType = pktTagType
1402
1403 switch pktTagType {
1404 case SingleTag:
1405 case DoubleTag:
1406 case Untagged:
1407 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001408 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301409 }
1410 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001411 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301412}
1413
Gamze Abaka724d0852020-03-18 12:10:24 +00001414func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001415 var actionCmd openoltpb2.ActionCmd
1416 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301417 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001418 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301419 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001420 if _, ok := actionInfo[VlanPcp]; ok {
1421 action.Cmd.RemarkInnerPbits = true
1422 action.IPbits = actionInfo[VlanPcp].(uint32)
1423 if _, ok := actionInfo[VlanVid]; ok {
1424 action.Cmd.TranslateInnerTag = true
1425 action.IVid = actionInfo[VlanVid].(uint32)
1426 }
1427 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001428 } else if _, ok := actionInfo[PushVlan]; ok {
1429 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301430 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001431 if _, ok := actionInfo[VlanPcp]; ok {
1432 action.OPbits = actionInfo[VlanPcp].(uint32)
1433 action.Cmd.RemarkOuterPbits = true
1434 if _, ok := classifierInfo[VlanVid]; ok {
1435 action.IVid = classifierInfo[VlanVid].(uint32)
1436 action.Cmd.TranslateInnerTag = true
1437 }
1438 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001439 } else if _, ok := actionInfo[TrapToHost]; ok {
1440 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301441 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001442 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301443 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001444 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301445}
1446
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001447// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001448func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1449 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301450}
1451
Gamze Abakafee36392019-10-03 11:17:24 +00001452// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301453func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1454 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001455 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1456
Gamze Abakafee36392019-10-03 11:17:24 +00001457 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301458 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001459 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301460 // return err
1461 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001462 }
Shrey Baid26912972020-04-16 21:02:31 +05301463 log.Debugw("tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001464 }
1465 return nil
1466}
1467
1468// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301469func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001470 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001471 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001472 }
npujarec5762e2020-01-01 14:08:48 +05301473 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301474 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1475 log.Fields{
1476 "tp-id": tpID,
1477 "uni-port-name": uniPortName,
1478 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001479 }
1480 return nil
1481}
1482
Neha Sharma96b7bf22020-06-15 10:37:32 +00001483func getFlowStoreCookie(ctx context.Context, classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301484 if len(classifier) == 0 { // should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00001485 logger.Error(ctx, "invalid-classfier-object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301486 return 0
1487 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001488 logger.Debugw(ctx, "generating-flow-store-cookie",
Shrey Baid26912972020-04-16 21:02:31 +05301489 log.Fields{
1490 "classifier": classifier,
1491 "gemport-id": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301492 var jsonData []byte
1493 var flowString string
1494 var err error
1495 // TODO: Do we need to marshall ??
1496 if jsonData, err = json.Marshal(classifier); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001497 logger.Error(ctx, "failed-to-encode-classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301498 return 0
1499 }
1500 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001501 if gemPortID != 0 {
1502 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301503 }
1504 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001505 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301506 hash := big.NewInt(0)
1507 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301508 generatedHash := hash.Uint64()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001509 logger.Debugw(ctx, "hash-generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301510 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301511}
1512
npujarec5762e2020-01-01 14:08:48 +05301513func (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 +05301514 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001515 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001516 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1517 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1518 */
1519 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001520 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001521 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001522 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001523 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001524 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301525 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001526 if existingFlows != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001527 logger.Debugw(ctx, "flow-exists-for-given-flowID--appending-it-to-current-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301528 log.Fields{
1529 "flow-id": flow.FlowId,
1530 "device-id": f.deviceHandler.device.Id,
1531 "intf-id": intfID,
1532 "onu-id": flow.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001533 //for _, f := range *existingFlows {
1534 // flows = append(flows, f)
1535 //}
1536 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001537 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001538 logger.Debugw(ctx, "updated-flows-for-given-flowID-and-onuid",
Shrey Baid26912972020-04-16 21:02:31 +05301539 log.Fields{
1540 "updatedflow": flows,
1541 "flow-id": flow.FlowId,
1542 "onu-id": flow.OnuId,
1543 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +05301544 return &flows
1545}
1546
npujarec5762e2020-01-01 14:08:48 +05301547func (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 +00001548 logger.Debugw(ctx, "storing-flow(s)-into-kv-store", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301549 "flow-id": flowID,
1550 "device-id": f.deviceHandler.device.Id,
1551 "intf-id": intfID,
1552 "onu-id": onuID})
npujarec5762e2020-01-01 14:08:48 +05301553 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001554 logger.Warnw(ctx, "error-while-storing-flow-into-kv-store", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301555 "device-id": f.deviceHandler.device.Id,
1556 "onu-id": onuID,
1557 "intf-id": intfID,
1558 "flow-id": flowID})
manikkaraj k17652a72019-05-06 09:06:36 -04001559 return err
1560 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001561 logger.Infow(ctx, "stored-flow(s)-into-kv-store-successfully!", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301562 "device-id": f.deviceHandler.device.Id,
1563 "onu-id": onuID,
1564 "intf-id": intfID,
1565 "flow-id": flowID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301566 return nil
1567}
1568
David K. Bainbridge794735f2020-02-11 21:01:37 -08001569func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001570
1571 var intfID uint32
1572 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1573 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1574 */
1575 if deviceFlow.AccessIntfId != -1 {
1576 intfID = uint32(deviceFlow.AccessIntfId)
1577 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001578 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001579 intfID = uint32(deviceFlow.NetworkIntfId)
1580 }
1581
Neha Sharma96b7bf22020-06-15 10:37:32 +00001582 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301583 "flow": *deviceFlow,
1584 "device-id": f.deviceHandler.device.Id,
1585 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001586 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001587
1588 st, _ := status.FromError(err)
1589 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001590 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001591 "err": err,
1592 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301593 "device-id": f.deviceHandler.device.Id,
1594 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001595 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301596 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001597
1598 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001599 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301600 log.Fields{"err": err,
1601 "device-flow": deviceFlow,
1602 "device-id": f.deviceHandler.device.Id,
1603 "intf-id": intfID})
npujarec5762e2020-01-01 14:08:48 +05301604 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001605 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001606 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301607 if deviceFlow.GemportId != -1 {
1608 // No need to register the flow if it is a trap on nni flow.
Kent Hagermane6ff1012020-07-14 15:07:53 -04001609 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1610 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1611 return err
1612 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301613 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001614 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301615 log.Fields{
1616 "flow": *deviceFlow,
1617 "device-id": f.deviceHandler.device.Id,
1618 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001619 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001620}
1621
Neha Sharma96b7bf22020-06-15 10:37:32 +00001622func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1623 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301624 log.Fields{
1625 "flow": *deviceFlow,
1626 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001627 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001628 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001629 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001630 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301631 log.Fields{
1632 "err": err,
1633 "deviceFlow": deviceFlow,
1634 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001635 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001636 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001637 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001638 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001639
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001640 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001641 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001642 "of-flow-id": ofFlowID,
1643 "flow": *deviceFlow,
1644 "device-id": f.deviceHandler.device.Id,
1645 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001646 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301647}
1648
David K. Bainbridge794735f2020-02-11 21:01:37 -08001649func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001650
1651 classifierInfo := make(map[string]interface{})
1652 actionInfo := make(map[string]interface{})
1653
1654 classifierInfo[EthType] = uint32(LldpEthType)
1655 classifierInfo[PacketTagType] = Untagged
1656 actionInfo[TrapToHost] = true
1657
1658 // LLDP flow is installed to trap LLDP packets on the NNI port.
1659 // We manage flow_id resource pool on per PON port basis.
1660 // Since this situation is tricky, as a hack, we pass the NNI port
1661 // index (network_intf_id) as PON port Index for the flow_id resource
1662 // pool. Also, there is no ONU Id available for trapping LLDP packets
1663 // on NNI port, use onu_id as -1 (invalid)
1664 // ****************** CAVEAT *******************
1665 // This logic works if the NNI Port Id falls within the same valid
1666 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1667 // we need to have a re-look at this.
1668 // *********************************************
1669
1670 var onuID = -1
1671 var uniID = -1
1672 var gemPortID = -1
1673
Neha Sharma96b7bf22020-06-15 10:37:32 +00001674 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001675 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301676 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001677 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001678 var flowStoreCookie = getFlowStoreCookie(ctx, classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301679 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001680 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001681 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001682 }
npujarec5762e2020-01-01 14:08:48 +05301683 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001684
1685 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301686 return olterrors.NewErrNotFound("flow-id",
1687 log.Fields{
1688 "interface-id": networkInterfaceID,
1689 "onu-id": onuID,
1690 "uni-id": uniID,
1691 "gem-port-id": gemPortID,
1692 "cookie": flowStoreCookie,
1693 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001694 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001695 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001696 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1697 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301698 return olterrors.NewErrInvalidValue(
1699 log.Fields{
1700 "classifier": classifierInfo,
1701 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001702 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001703 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301704 log.Fields{
1705 "classifier": *classifierProto,
1706 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001707 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001708 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301709 return olterrors.NewErrInvalidValue(
1710 log.Fields{
1711 "action": actionInfo,
1712 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001713 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001714 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301715 log.Fields{
1716 "action": *actionProto,
1717 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001718
1719 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1720 OnuId: int32(onuID), // OnuId not required
1721 UniId: int32(uniID), // UniId not used
1722 FlowId: flowID,
1723 FlowType: Downstream,
1724 NetworkIntfId: int32(networkInterfaceID),
1725 GemportId: int32(gemPortID),
1726 Classifier: classifierProto,
1727 Action: actionProto,
1728 Priority: int32(flow.Priority),
1729 Cookie: flow.Cookie,
1730 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001731 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301732 return olterrors.NewErrFlowOp("add", flowID,
1733 log.Fields{
1734 "flow": downstreamflow,
1735 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001736 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001737 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301738 log.Fields{
1739 "device-id": f.deviceHandler.device.Id,
1740 "onu-id": onuID,
1741 "flow-id": flowID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001742 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1743 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1744 int32(onuID),
1745 int32(uniID),
1746 flowID, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301747 return olterrors.NewErrPersistence("update", "flow", flowID,
1748 log.Fields{
1749 "flow": downstreamflow,
1750 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001751 }
1752 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301753}
1754
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001755func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1756 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001757}
1758
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001759//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001760func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001761 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1762 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1763 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001764 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301765 log.Fields{
1766 "intf-id": intfID,
1767 "onu-id": onuID,
1768 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001769 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001770 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301771 return nil, olterrors.NewErrNotFound("onu-child-device",
1772 log.Fields{
1773 "onu-id": onuID,
1774 "intf-id": intfID,
1775 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001776 }
1777 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1778 //better to ad the device to cache here.
1779 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1780 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001781 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301782 log.Fields{
1783 "intf-id": intfID,
1784 "onu-id": onuID,
1785 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001786 }
1787
1788 return onuDev.(*OnuDevice), nil
1789}
1790
1791//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001792func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1793 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301794 log.Fields{
1795 "pon-port": intfID,
1796 "onu-id": onuID,
1797 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001798 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001799 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001800 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301801 return nil, olterrors.NewErrNotFound("onu",
1802 log.Fields{
1803 "interface-id": parentPortNo,
1804 "onu-id": onuID,
1805 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001806 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301807 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001808 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301809 log.Fields{
1810 "device-id": f.deviceHandler.device.Id,
1811 "child_device_id": onuDevice.Id,
1812 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301813 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301814}
1815
Neha Sharma96b7bf22020-06-15 10:37:32 +00001816func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1817 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301818 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001819 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301820 log.Fields{
1821 "intf-id": intfID,
1822 "onu-id": onuID,
1823 "uni-id": uniID,
1824 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001825 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301826 }
1827
1828 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001829 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301830 log.Fields{
1831 "msg": *delGemPortMsg,
1832 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001833 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301834 delGemPortMsg,
1835 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301836 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001837 onuDev.deviceType,
1838 onuDev.deviceID,
1839 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301840 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1841 log.Fields{
1842 "from-adapter": f.deviceHandler.device.Type,
1843 "to-adapter": onuDev.deviceType,
1844 "onu-id": onuDev.deviceID,
1845 "proxyDeviceID": onuDev.proxyDeviceID,
1846 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301847 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001848 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301849 log.Fields{
1850 "msg": delGemPortMsg,
1851 "from-adapter": f.deviceHandler.device.Type,
1852 "to-adapter": onuDev.deviceType,
1853 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301854 return nil
1855}
1856
Neha Sharma96b7bf22020-06-15 10:37:32 +00001857func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1858 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301859 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001860 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301861 log.Fields{
1862 "intf-id": intfID,
1863 "onu-id": onuID,
1864 "uni-id": uniID,
1865 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001866 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301867 }
1868
1869 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001870 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301871 log.Fields{
1872 "msg": *delTcontMsg,
1873 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001874 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301875 delTcontMsg,
1876 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301877 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001878 onuDev.deviceType,
1879 onuDev.deviceID,
1880 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301881 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1882 log.Fields{
1883 "from-adapter": f.deviceHandler.device.Type,
1884 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1885 "proxyDeviceID": onuDev.proxyDeviceID,
1886 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301887 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001888 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301889 log.Fields{
1890 "msg": delTcontMsg,
1891 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301892 return nil
1893}
1894
Neha Sharma96b7bf22020-06-15 10:37:32 +00001895func (f *OpenOltFlowMgr) deletePendingFlows(ctx context.Context, Intf uint32, onuID int32, uniID int32) {
Girish Gowdra3d633032019-12-10 16:37:05 +05301896 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1897 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1898 if val.(int) > 0 {
1899 pnFlDels := val.(int) - 1
1900 if pnFlDels > 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001901 logger.Debugw(ctx, "flow-delete-succeeded--more-pending",
Shrey Baid26912972020-04-16 21:02:31 +05301902 log.Fields{
1903 "intf": Intf,
1904 "onu-id": onuID,
1905 "uni-id": uniID,
1906 "currpendingflowcnt": pnFlDels,
1907 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301908 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1909 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001910 logger.Debugw(ctx, "all-pending-flow-deletes-handled--removing-entry-from-map",
Shrey Baid26912972020-04-16 21:02:31 +05301911 log.Fields{
1912 "intf": Intf,
1913 "onu-id": onuID,
1914 "uni-id": uniID,
1915 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301916 f.pendingFlowDelete.Delete(pnFlDelKey)
1917 }
1918 }
1919 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001920 logger.Debugw(ctx, "no-pending-delete-flows-found",
Shrey Baid26912972020-04-16 21:02:31 +05301921 log.Fields{
1922 "intf": Intf,
1923 "onu-id": onuID,
1924 "uni-id": uniID,
1925 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301926
1927 }
1928
1929}
1930
Girish Gowdrac3037402020-01-22 20:29:53 +05301931// Once the gemport is released for a given onu, it also has to be cleared from local cache
1932// which was used for deriving the gemport->logicalPortNo during packet-in.
1933// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1934// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001935func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001936
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001937 f.onuGemInfoLock.Lock()
1938 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001939
Neha Sharma96b7bf22020-06-15 10:37:32 +00001940 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301941 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001942 "gem-port-id": gemPortID,
1943 "intf-id": intfID,
1944 "onu-id": onuID,
1945 "device-id": f.deviceHandler.device.Id,
1946 "onu-gem": f.onuGemInfo[intfID]})
Girish Gowdrac3037402020-01-22 20:29:53 +05301947 onugem := f.onuGemInfo[intfID]
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001948deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001949 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301950 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001951 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301952 // If the gemport is found, delete it from local cache.
1953 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001954 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1955 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001956 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301957 log.Fields{
1958 "intf-id": intfID,
1959 "onu-id": onuID,
1960 "deletedgemport-id": gemPortID,
1961 "gemports": onu.GemPorts,
1962 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001963 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301964 }
1965 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001966 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301967 }
1968 }
1969}
1970
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301971//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001972// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301973func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301974 gemPortID int32, flowID uint32, flowDirection string,
1975 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001976
Neha Sharma96b7bf22020-06-15 10:37:32 +00001977 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001978 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301979 return olterrors.NewErrNotFound("tp-id",
1980 log.Fields{
1981 "flow": flow,
1982 "intf": Intf,
1983 "onu-id": onuID,
1984 "uni-id": uniID,
1985 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001986 }
Gamze Abakafee36392019-10-03 11:17:24 +00001987
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001988 if len(updatedFlows) >= 0 {
1989 // There are still flows referencing the same flow_id.
1990 // So the flow should not be freed yet.
1991 // For ex: Case of HSIA where same flow is shared
1992 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00001993 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001994 _ = olterrors.NewErrPersistence("update", "flow", flowID,
Shrey Baid26912972020-04-16 21:02:31 +05301995 log.Fields{
1996 "flow": updatedFlows,
1997 "device-id": f.deviceHandler.device.Id}, err).Log()
Girish Kumarf26e4882020-03-05 06:49:10 +00001998 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001999 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05302000 // Do this for subscriber flows only (not trap from NNI flows)
2001 if onuID != -1 && uniID != -1 {
2002 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
2003 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002004 logger.Debugw(ctx, "creating-entry-for-pending-flow-delete",
Shrey Baid26912972020-04-16 21:02:31 +05302005 log.Fields{
2006 "flow-id": flowID,
2007 "intf": Intf,
2008 "onu-id": onuID,
2009 "uni-id": uniID,
2010 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302011 f.pendingFlowDelete.Store(pnFlDelKey, 1)
2012 } else {
2013 pnFlDels := val.(int) + 1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002014 logger.Debugw(ctx, "updating-flow-delete-entry",
Shrey Baid26912972020-04-16 21:02:31 +05302015 log.Fields{
2016 "flow-id": flowID,
2017 "intf": Intf,
2018 "onu-id": onuID,
2019 "uni-id": uniID,
2020 "currPendingFlowCnt": pnFlDels,
2021 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302022 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
2023 }
2024
Neha Sharma96b7bf22020-06-15 10:37:32 +00002025 defer f.deletePendingFlows(ctx, Intf, onuID, uniID)
Girish Gowdra3d633032019-12-10 16:37:05 +05302026 }
2027
Neha Sharma96b7bf22020-06-15 10:37:32 +00002028 logger.Debugw(ctx, "releasing-flow-id-to-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302029 log.Fields{
2030 "Intf": Intf,
2031 "onu-id": onuID,
2032 "uni-id": uniID,
2033 "flow-id": flowID,
2034 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302035 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002036
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002037 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002038 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
2039 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
Shrey Baid26912972020-04-16 21:02:31 +05302040 log.Fields{
2041 "TP-PATH": tpPath,
2042 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302043 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00002044 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +05302045 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
2046 log.Fields{
2047 "tp-id": tpID,
2048 "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002049 }
2050
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302051 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00002052 if f.isGemPortUsedByAnotherFlow(gemPK) {
2053 flowIDs := f.flowsUsedByGemPort[gemPK]
2054 for i, flowIDinMap := range flowIDs {
2055 if flowIDinMap == flowID {
2056 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302057 // everytime flowsUsedByGemPort cache is updated the same should be updated
2058 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002059 f.flowsUsedByGemPort[gemPK] = flowIDs
Kent Hagermane6ff1012020-07-14 15:07:53 -04002060 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs); err != nil {
2061 return err
2062 }
Gamze Abakafee36392019-10-03 11:17:24 +00002063 break
2064 }
2065 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002066 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
Shrey Baid26912972020-04-16 21:02:31 +05302067 log.Fields{
2068 "gemport-id": gemPortID,
2069 "usedByFlows": flowIDs,
2070 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302071 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00002072 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002073 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05302074 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002075 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
2076 // 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 +05302077 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002078 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002079 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302080 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
2081 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002082 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05302083 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
2084 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002085 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05302086 // Delete the gem port on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002087 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
2088 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302089 log.Fields{
2090 "err": err,
2091 "intf": Intf,
2092 "onu-id": onuID,
2093 "uni-id": uniID,
2094 "device-id": f.deviceHandler.device.Id,
2095 "gemport-id": gemPortID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302096 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002097 switch techprofileInst := techprofileInst.(type) {
2098 case *tp.TechProfile:
2099 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
2100 if !ok {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002101 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
2102 logger.Warn(ctx, err)
2103 }
2104 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2105 logger.Warn(ctx, err)
2106 }
2107 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 {
2108 logger.Warn(ctx, err)
2109 }
2110 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 {
2111 logger.Warn(ctx, err)
2112 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002113 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
2114 // Delete the TCONT on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002115 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
2116 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002117 log.Fields{
2118 "intf": Intf,
2119 "onu-id": onuID,
2120 "uni-id": uniID,
2121 "device-id": f.deviceHandler.device.Id,
2122 "alloc-id": techprofileInst.UsScheduler.AllocID})
2123 }
2124 }
2125 case *tp.EponProfile:
Kent Hagermane6ff1012020-07-14 15:07:53 -04002126 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
2127 logger.Warn(ctx, err)
2128 }
2129 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2130 logger.Warn(ctx, err)
2131 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002132 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302133 // Delete the TCONT on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002134 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.AllocID), tpPath); err != nil {
2135 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302136 log.Fields{
2137 "intf": Intf,
2138 "onu-id": onuID,
2139 "uni-id": uniID,
2140 "device-id": f.deviceHandler.device.Id,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002141 "alloc-id": techprofileInst.AllocID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302142 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002143 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002144 logger.Errorw(ctx, "error-unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002145 log.Fields{
2146 "techprofileInst": techprofileInst})
Gamze Abakafee36392019-10-03 11:17:24 +00002147 }
2148 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002149 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302150 return nil
2151}
2152
David K. Bainbridge794735f2020-02-11 21:01:37 -08002153// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302154func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302155
Neha Sharma96b7bf22020-06-15 10:37:32 +00002156 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302157 log.Fields{
2158 "flowDirection": flowDirection,
2159 "flow": *flow,
2160 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002161
2162 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05302163 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002164 return
2165 }
2166
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302167 classifierInfo := make(map[string]interface{})
2168
Neha Sharma96b7bf22020-06-15 10:37:32 +00002169 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302170 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002171 logger.Error(ctx, err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302172 return
2173 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302174
David K. Bainbridge794735f2020-02-11 21:01:37 -08002175 onuID := int32(onu)
2176 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302177
2178 for _, field := range flows.GetOfbFields(flow) {
2179 if field.Type == flows.IP_PROTO {
2180 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002181 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302182 }
2183 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002184 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302185 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002186 "flow-id": flow.Id,
2187 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302188 "onu-id": onuID,
2189 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302190
2191 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2192 onuID = -1
2193 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002194 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2195 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002196 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002197 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002198 log.Fields{
2199 "port-number": inPort,
2200 "error": err})
2201 return
2202 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302203 }
npujarec5762e2020-01-01 14:08:48 +05302204 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002205 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302206 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302207 if flowInfo == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002208 logger.Debugw(ctx, "no-flowinfo-found-in-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302209 log.Fields{
2210 "intf": Intf,
2211 "onu-id": onuID,
2212 "uni-id": uniID,
2213 "flow-id": flowID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302214 return
2215 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302216
Kent Hagermane6ff1012020-07-14 15:07:53 -04002217 updatedFlows := *flowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302218 for i, storedFlow := range updatedFlows {
2219 if flow.Id == storedFlow.LogicalFlowID {
2220 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002221 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002222 // DKB
Neha Sharma96b7bf22020-06-15 10:37:32 +00002223 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2224 logger.Errorw(ctx, "failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002225 return
2226 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002227 logger.Info(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002228 "flow-id": flow.Id,
2229 "stored-flow": storedFlow,
2230 "device-id": f.deviceHandler.device.Id,
2231 "stored-flow-id": flowID,
2232 "onu-id": onuID,
2233 "intf": Intf,
2234 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08002235 //Remove the Flow from FlowInfo
2236 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
2237 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
2238 flowID, flowDirection, portNum, updatedFlows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002239 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002240 "flow-id": flow.Id,
2241 "stored-flow": storedFlow,
2242 "device-id": f.deviceHandler.device.Id,
2243 "stored-flow-id": flowID,
2244 "onu-id": onuID,
2245 "intf": Intf,
2246 })
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302247 return
2248 }
2249 }
2250 }
2251 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002252}
2253
Esin Karamanccb714b2019-11-29 15:02:06 +00002254//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
2255// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05302256func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002257 classifierInfo := make(map[string]interface{})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002258 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00002259 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002260
2261 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002262 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 +00002263 return
2264 }
2265
Esin Karamanccb714b2019-11-29 15:02:06 +00002266 var onuID = int32(NoneOnuID)
2267 var uniID = int32(NoneUniID)
2268 var flowID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00002269
npujarec5762e2020-01-01 14:08:48 +05302270 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002271
2272 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302273 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002274 if flowInfo == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002275 logger.Debugw(ctx, "no-multicast-flowinfo-found-in-the-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302276 log.Fields{
2277 "intf": networkInterfaceID,
2278 "onu-id": onuID,
2279 "uni-id": uniID,
2280 "flow-id": flowID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002281 continue
2282 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002283 updatedFlows := *flowInfo
Esin Karamanccb714b2019-11-29 15:02:06 +00002284 for i, storedFlow := range updatedFlows {
2285 if flow.Id == storedFlow.LogicalFlowID {
2286 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002287 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302288 log.Fields{
2289 "flow": storedFlow,
2290 "flow-id": flow.Id,
2291 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002292 //remove from device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002293 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002294 // DKB
Neha Sharma96b7bf22020-06-15 10:37:32 +00002295 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002296 log.Fields{
2297 "flow-id": flow.Id,
2298 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002299 return
2300 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002301 logger.Infow(ctx, "multicast-flow-removed-from-device-successfully", log.Fields{"flow-id": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002302 //Remove the Flow from FlowInfo
2303 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05302304 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002305 logger.Errorw(ctx, "failed-to-delete-multicast-flow-from-the-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302306 log.Fields{"flow": storedFlow,
2307 "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002308 return
2309 }
2310 //release flow id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002311 logger.Debugw(ctx, "releasing-multicast-flow-id",
Shrey Baid26912972020-04-16 21:02:31 +05302312 log.Fields{"flow-id": flowID,
2313 "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05302314 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002315 }
2316 }
2317 }
2318}
2319
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002320//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002321func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002322 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302323 var direction string
2324 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002325
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302326 for _, action := range flows.GetActions(flow) {
2327 if action.Type == flows.OUTPUT {
2328 if out := action.GetOutput(); out != nil {
2329 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002330 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302331 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002332 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002333 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002334 }
2335 }
2336 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002337
2338 if flows.HasGroup(flow) {
2339 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07002340 f.clearFlowFromResourceManager(ctx, flow, direction)
2341 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002342 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302343 direction = Upstream
2344 } else {
2345 direction = Downstream
2346 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302347
Neha Sharma96b7bf22020-06-15 10:37:32 +00002348 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002349 if err != nil {
2350 return err
2351 }
2352
2353 userKey := tpLockKey{intfID, onuID, uniID}
2354
2355 // Serialize flow removes on a per subscriber basis
2356 if f.perUserFlowHandleLock.TryLock(userKey) {
2357 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
2358 f.perUserFlowHandleLock.Unlock(userKey)
2359 } else {
2360 // Ideally this should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00002361 logger.Errorw(ctx, "failed-to-acquire-lock-to-remove-flow--remove-aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07002362 return errors.New("failed-to-acquire-per-user-lock")
2363 }
2364
2365 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002366}
2367
Girish Gowdra3d633032019-12-10 16:37:05 +05302368func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
2369 uniID uint32, ch chan bool) {
2370 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2371 for {
2372 select {
2373 case <-time.After(20 * time.Millisecond):
2374 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002375 logger.Debug(ctx, "pending-flow-deletes-completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05302376 ch <- true
2377 return
2378 }
2379 case <-ctx.Done():
Neha Sharma96b7bf22020-06-15 10:37:32 +00002380 logger.Error(ctx, "flow-delete-wait-handler-routine-canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05302381 return
2382 }
2383 }
2384}
2385
Esin Karamanae41e2b2019-12-17 18:13:13 +00002386//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2387func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2388 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2389 if ethType, ok := classifierInfo[EthType]; ok {
2390 if ethType.(uint32) == IPv4EthType {
2391 if ipProto, ok := classifierInfo[IPProto]; ok {
2392 if ipProto.(uint32) == IgmpProto {
2393 return true
2394 }
2395 }
2396 }
2397 }
2398 }
2399 return false
2400}
2401
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002402// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302403// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002404func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002405 classifierInfo := make(map[string]interface{})
2406 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002407 var UsMeterID uint32
2408 var DsMeterID uint32
2409
Neha Sharma96b7bf22020-06-15 10:37:32 +00002410 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302411 log.Fields{
2412 "flow": flow,
2413 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002414 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002415
Neha Sharma96b7bf22020-06-15 10:37:32 +00002416 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002417 if err != nil {
2418 // Error logging is already done in the called function
2419 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002420 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302421 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002422
Esin Karamanccb714b2019-11-29 15:02:06 +00002423 if flows.HasGroup(flow) {
2424 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002425 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002426 }
2427
manikkaraj k17652a72019-05-06 09:06:36 -04002428 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002429 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002430 if err != nil {
2431 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002432 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002433 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002434
Neha Sharma96b7bf22020-06-15 10:37:32 +00002435 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302436 log.Fields{
2437 "classifierinfo_inport": classifierInfo[InPort],
2438 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002439 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002440
Humera Kouser94d7a842019-08-25 19:04:32 -04002441 if ethType, ok := classifierInfo[EthType]; ok {
2442 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002443 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002444 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002445 }
2446 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002447 if ipProto, ok := classifierInfo[IPProto]; ok {
2448 if ipProto.(uint32) == IPProtoDhcp {
2449 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302450 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002451 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002452 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002453 }
2454 }
2455 }
2456 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002457 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002458 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002459 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002460 }
A R Karthick1f85b802019-10-11 05:06:05 +00002461
Neha Sharma96b7bf22020-06-15 10:37:32 +00002462 f.deviceHandler.AddUniPortToOnu(ctx, intfID, onuID, portNo)
npujarec5762e2020-01-01 14:08:48 +05302463 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002464
Neha Sharma96b7bf22020-06-15 10:37:32 +00002465 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002466 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302467 return olterrors.NewErrNotFound("tpid-for-flow",
2468 log.Fields{
2469 "flow": flow,
2470 "intf-id": IntfID,
2471 "onu-id": onuID,
2472 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002473 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002474 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302475 log.Fields{
2476 "tp-id": TpID,
2477 "intf-id": intfID,
2478 "onu-id": onuID,
2479 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002480 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002481 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002482 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002483 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002484 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002485 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002486
2487 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302488
2489 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2490 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002491 logger.Debugw(ctx, "no-pending-flows-found--going-ahead-with-flow-install",
Shrey Baid26912972020-04-16 21:02:31 +05302492 log.Fields{
2493 "intf-id": intfID,
2494 "onu-id": onuID,
2495 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302496 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302497 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05302498 pendingFlowDelComplete := make(chan bool)
2499 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
2500 select {
2501 case <-pendingFlowDelComplete:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002502 logger.Debugw(ctx, "all-pending-flow-deletes-completed",
Shrey Baid26912972020-04-16 21:02:31 +05302503 log.Fields{
2504 "intf-id": intfID,
2505 "onu-id": onuID,
2506 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302507 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302508
2509 case <-time.After(10 * time.Second):
Shrey Baid26912972020-04-16 21:02:31 +05302510 return olterrors.NewErrTimeout("pending-flow-deletes",
2511 log.Fields{
2512 "intf-id": intfID,
2513 "onu-id": onuID,
2514 "uni-id": uniID}, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +05302515 }
2516 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002517 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002518}
2519
Esin Karamanccb714b2019-11-29 15:02:06 +00002520// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002521func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002522 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002523 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302524 "classifier-info": classifierInfo,
2525 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002526
Esin Karaman65409d82020-03-18 10:58:18 +00002527 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002528 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002529 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002530 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002531 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
2532 //otherwise, classification is based on ipv4_dst by default.
2533 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
2534 mcastFlowClassificationByEthDst := false
2535
2536 if mcastFlowClassificationByEthDst {
2537 //replace ipDst with ethDst
2538 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
2539 flows.IsMulticastIp(ipv4Dst.(uint32)) {
2540 // replace ipv4_dst classifier with eth_dst
2541 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
2542 delete(classifierInfo, Ipv4Dst)
2543 classifierInfo[EthDst] = multicastMac
Neha Sharma96b7bf22020-06-15 10:37:32 +00002544 logger.Debugw(ctx, "multicast-ip-to-mac-conversion-success",
Shrey Baid26912972020-04-16 21:02:31 +05302545 log.Fields{
2546 "ip:": ipv4Dst.(uint32),
2547 "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002548 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002549 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002550 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002551
David K. Bainbridge794735f2020-02-11 21:01:37 -08002552 onuID := NoneOnuID
2553 uniID := NoneUniID
2554 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00002555
Neha Sharma96b7bf22020-06-15 10:37:32 +00002556 flowStoreCookie := getFlowStoreCookie(ctx, classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302557 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002558 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002559 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002560 }
npujarec5762e2020-01-01 14:08:48 +05302561 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00002562 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302563 return olterrors.NewErrNotFound("multicast-flow-id",
2564 log.Fields{
2565 "interface-id": networkInterfaceID,
2566 "onu-id": onuID,
2567 "uni-id": uniID,
2568 "gem-port-id": gemPortID,
2569 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002570 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002571 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002572 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2573 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002574 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002575 }
2576 groupID := actionInfo[GroupID].(uint32)
2577 multicastFlow := openoltpb2.Flow{
2578 FlowId: flowID,
2579 FlowType: Multicast,
2580 NetworkIntfId: int32(networkInterfaceID),
2581 GroupId: groupID,
2582 Classifier: classifierProto,
2583 Priority: int32(flow.Priority),
2584 Cookie: flow.Cookie}
2585
Kent Hagermane6ff1012020-07-14 15:07:53 -04002586 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002587 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002588 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002589 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002590 //get cached group
Kent Hagermane6ff1012020-07-14 15:07:53 -04002591 if group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002592 //calling groupAdd to set group members after multicast flow creation
Kent Hagermane6ff1012020-07-14 15:07:53 -04002593 if err := f.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002594 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002595 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002596 //cached group can be removed now
2597 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2598 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2599 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002600 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002601
2602 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2603 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2604 int32(onuID),
2605 int32(uniID),
2606 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002607 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002608 }
2609 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002610}
2611
Esin Karaman65409d82020-03-18 10:58:18 +00002612//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2613func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2614 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002615 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002616 if err != nil {
2617 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2618 }
2619 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002620 }
Esin Karaman65409d82020-03-18 10:58:18 +00002621 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302622 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002623 if e == nil && len(nniPorts) > 0 {
2624 return nniPorts[0], nil
2625 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302626 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002627}
2628
2629// AddGroup add or update the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002630func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002631 logger.Infow(ctx, "add-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002632 if group == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002633 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002634 }
2635
2636 groupToOlt := openoltpb2.Group{
2637 GroupId: group.Desc.GroupId,
2638 Command: openoltpb2.Group_SET_MEMBERS,
2639 Action: f.buildGroupAction(),
2640 }
2641
Neha Sharma96b7bf22020-06-15 10:37:32 +00002642 logger.Debugw(ctx, "sending-group-to-device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05302643 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002644 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002645 return olterrors.NewErrAdapter("add-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002646 }
2647 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05302648 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002649 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002650 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002651 logger.Infow(ctx, "add-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002652 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002653}
2654
Esin Karamand519bbf2020-07-01 11:16:03 +00002655// DeleteGroup deletes a group from the device
2656func (f *OpenOltFlowMgr) DeleteGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
2657 logger.Debugw(ctx, "delete-group", log.Fields{"group": group})
2658 if group == nil {
2659 logger.Error(ctx, "unable-to-delete-group--invalid-argument--group-is-nil")
2660 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
2661 }
2662
2663 groupToOlt := openoltpb2.Group{
2664 GroupId: group.Desc.GroupId,
2665 }
2666
2667 logger.Debugw(ctx, "deleting-group-from-device", log.Fields{"groupToOlt": groupToOlt})
2668 _, err := f.deviceHandler.Client.DeleteGroup(ctx, &groupToOlt)
2669 if err != nil {
2670 logger.Errorw(ctx, "delete-group-failed-on-dev", log.Fields{"groupToOlt": groupToOlt, "err": err})
2671 return olterrors.NewErrAdapter("delete-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
2672 }
2673 //remove group from the store
2674 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, group.Desc.GroupId, false); err != nil {
2675 return olterrors.NewErrPersistence("delete", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
2676 }
2677 logger.Debugw(ctx, "delete-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
2678 return nil
2679}
2680
Esin Karamanccb714b2019-11-29 15:02:06 +00002681//buildGroupAction creates and returns a group action
2682func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2683 var actionCmd openoltpb2.ActionCmd
2684 var action openoltpb2.Action
2685 action.Cmd = &actionCmd
2686 //pop outer vlan
2687 action.Cmd.RemoveOuterTag = true
2688 return &action
2689}
2690
2691// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002692func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002693 logger.Infow(ctx, "modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002694 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002695 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002696 }
2697
Neha Sharma96b7bf22020-06-15 10:37:32 +00002698 newGroup := f.buildGroup(ctx, group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002699 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302700 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002701
2702 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002703 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002704 }
2705
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002706 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002707 if groupExists {
2708 // group already exists
Neha Sharma96b7bf22020-06-15 10:37:32 +00002709 current = f.buildGroup(ctx, group.Desc.GroupId, val.Desc.GetBuckets())
2710 logger.Debugw(ctx, "modify-group--group exists",
Shrey Baid26912972020-04-16 21:02:31 +05302711 log.Fields{
2712 "group on the device": val,
2713 "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002714 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002715 current = f.buildGroup(ctx, group.Desc.GroupId, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002716 }
2717
Neha Sharma96b7bf22020-06-15 10:37:32 +00002718 logger.Debugw(ctx, "modify-group--comparing-current-and-new",
Shrey Baid26912972020-04-16 21:02:31 +05302719 log.Fields{
2720 "group on the device": current,
2721 "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002722 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002723 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002724 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002725 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002726
Neha Sharma96b7bf22020-06-15 10:37:32 +00002727 logger.Infow(ctx, "modify-group--differences found", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302728 "membersToBeAdded": membersToBeAdded,
2729 "membersToBeRemoved": membersToBeRemoved,
2730 "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002731
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002732 groupToOlt := openoltpb2.Group{
2733 GroupId: group.Desc.GroupId,
2734 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002735 var errAdd, errRemoved error
Kent Hagermane6ff1012020-07-14 15:07:53 -04002736 if len(membersToBeAdded) > 0 {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002737 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2738 groupToOlt.Members = membersToBeAdded
2739 //execute addMembers
Neha Sharma96b7bf22020-06-15 10:37:32 +00002740 errAdd = f.callGroupAddRemove(ctx, &groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002741 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002742 if len(membersToBeRemoved) > 0 {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002743 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2744 groupToOlt.Members = membersToBeRemoved
2745 //execute removeMembers
Neha Sharma96b7bf22020-06-15 10:37:32 +00002746 errRemoved = f.callGroupAddRemove(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002747 }
2748
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002749 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002750 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302751 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002752 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002753 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002754 logger.Infow(ctx, "modify-group-was-success--storing-group",
Shrey Baid26912972020-04-16 21:02:31 +05302755 log.Fields{
2756 "group": group,
2757 "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002758 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002759 logger.Warnw(ctx, "one-of-the-group-add/remove-operations-failed--cannot-save-group-modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002760 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002761 if errAdd != nil {
2762 return errAdd
2763 }
2764 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002765 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002766 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002767}
2768
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002769//callGroupAddRemove performs add/remove buckets operation for the indicated group
Neha Sharma96b7bf22020-06-15 10:37:32 +00002770func (f *OpenOltFlowMgr) callGroupAddRemove(ctx context.Context, group *openoltpb2.Group) error {
2771 if err := f.performGroupOperation(ctx, group); err != nil {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002772 st, _ := status.FromError(err)
2773 //ignore already exists error code
2774 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002775 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002776 }
2777 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002778 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002779}
2780
2781//findDiff compares group members and finds members which only exists in groups2
2782func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2783 var members []*openoltpb2.GroupMember
2784 for _, bucket := range group2.Members {
2785 if !f.contains(group1.Members, bucket) {
2786 // bucket does not exist and must be added
2787 members = append(members, bucket)
2788 }
2789 }
2790 return members
2791}
2792
2793//contains returns true if the members list contains the given member; false otherwise
2794func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2795 for _, groupMember := range members {
2796 if groupMember.InterfaceId == member.InterfaceId {
2797 return true
2798 }
2799 }
2800 return false
2801}
2802
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002803//performGroupOperation call performGroupOperation operation of openolt proto
Neha Sharma96b7bf22020-06-15 10:37:32 +00002804func (f *OpenOltFlowMgr) performGroupOperation(ctx context.Context, group *openoltpb2.Group) error {
2805 logger.Debugw(ctx, "sending-group-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05302806 log.Fields{
2807 "groupToOlt": group,
2808 "command": group.Command})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002809 _, err := f.deviceHandler.Client.PerformGroupOperation(log.WithSpanFromContext(context.Background(), ctx), group)
Esin Karamanccb714b2019-11-29 15:02:06 +00002810 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002811 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002812 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002813 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002814}
2815
2816//buildGroup build openoltpb2.Group from given group id and bucket list
Neha Sharma96b7bf22020-06-15 10:37:32 +00002817func (f *OpenOltFlowMgr) buildGroup(ctx context.Context, groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
Esin Karamanccb714b2019-11-29 15:02:06 +00002818 group := openoltpb2.Group{
2819 GroupId: groupID}
2820 // create members of the group
Kent Hagermane6ff1012020-07-14 15:07:53 -04002821 for _, ofBucket := range buckets {
2822 member := f.buildMember(ctx, ofBucket)
2823 if member != nil && !f.contains(group.Members, member) {
2824 group.Members = append(group.Members, member)
Esin Karamanccb714b2019-11-29 15:02:06 +00002825 }
2826 }
2827 return &group
2828}
2829
2830//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
Neha Sharma96b7bf22020-06-15 10:37:32 +00002831func (f *OpenOltFlowMgr) buildMember(ctx context.Context, ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
Esin Karamanccb714b2019-11-29 15:02:06 +00002832 var outPort uint32
2833 outPortFound := false
2834 for _, ofAction := range ofBucket.Actions {
2835 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2836 outPort = ofAction.GetOutput().Port
2837 outPortFound = true
2838 }
2839 }
2840
2841 if !outPortFound {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002842 logger.Debugw(ctx, "bucket-skipped-since-no-out-port-found-in-it", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002843 return nil
2844 }
2845 interfaceID := IntfIDFromUniPortNum(outPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002846 logger.Debugw(ctx, "got-associated-interface-id-of-the-port",
Shrey Baid26912972020-04-16 21:02:31 +05302847 log.Fields{
2848 "portNumber:": outPort,
2849 "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002850 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2851 member := openoltpb2.GroupMember{
2852 InterfaceId: interfaceID,
2853 InterfaceType: openoltpb2.GroupMember_PON,
2854 GemPortId: groupInfo.gemPortID,
2855 Priority: groupInfo.servicePriority,
2856 }
2857 //add member to the group
2858 return &member
2859 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002860 logger.Warnf(ctx, "bucket-skipped-since-interface-2-gem-mapping-cannot-be-found", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002861 return nil
2862}
2863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002864//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002865func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002866
Neha Sharma96b7bf22020-06-15 10:37:32 +00002867 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302868 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002869 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302870 log.Fields{
2871 "intf-id": intfID,
2872 "onu-id": onuID,
2873 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002874 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302875 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002876 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002877
Neha Sharma96b7bf22020-06-15 10:37:32 +00002878 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002879 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002880 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002881 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002882 tpDownloadMsg,
2883 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302884 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002885 onuDev.deviceType,
2886 onuDev.deviceID,
2887 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002888 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302889 return olterrors.NewErrCommunication("send-techprofile-download-request",
2890 log.Fields{
2891 "from-adapter": f.deviceHandler.device.Type,
2892 "to-adapter": onuDev.deviceType,
2893 "onu-id": onuDev.deviceID,
2894 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002895 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002896 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302897 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302898}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002899
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302900//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002901func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302902
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002903 f.onuGemInfoLock.Lock()
2904 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002905
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302906 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2907 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002908 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002909 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302910 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002911 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302912 log.Fields{
2913 "intf-id": intfID,
2914 "onu-id": onuID,
2915 "serial-num": serialNum,
2916 "onu": onu,
2917 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002918 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002919}
2920
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302921//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302922func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002923
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002924 f.onuGemInfoLock.Lock()
2925 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002926
Neha Sharma96b7bf22020-06-15 10:37:32 +00002927 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302928 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002929 "gem-port-id": gemPort,
2930 "intf-id": intfID,
2931 "onu-id": onuID,
2932 "device-id": f.deviceHandler.device.Id,
2933 "onu-gem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302934 onugem := f.onuGemInfo[intfID]
2935 // update the gem to the local cache as well as to kv strore
2936 for idx, onu := range onugem {
2937 if onu.OnuID == onuID {
2938 // check if gem already exists , else update the cache and kvstore
2939 for _, gem := range onu.GemPorts {
2940 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002941 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302942 log.Fields{
2943 "gem": gemPort,
2944 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302945 return
2946 }
2947 }
2948 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2949 f.onuGemInfo[intfID] = onugem
2950 }
2951 }
npujarec5762e2020-01-01 14:08:48 +05302952 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302953 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002954 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302955 log.Fields{
2956 "intf-id": intfID,
2957 "onu-id": onuID,
2958 "gemPort": gemPort,
2959 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002960 return
2961 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002962 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302963 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002964 "gem-port-id": gemPort,
2965 "intf-id": intfID,
2966 "onu-id": onuID,
2967 "device-id": f.deviceHandler.device.Id,
2968 "onu-gem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002969}
2970
2971// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002972
2973//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 +00002974func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302975
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002976 f.onuGemInfoLock.RLock()
2977 defer f.onuGemInfoLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302978
Neha Sharma96b7bf22020-06-15 10:37:32 +00002979 logger.Infow(ctx, "getting-onu-id-from-gem-port-and-pon-port",
Shrey Baid26912972020-04-16 21:02:31 +05302980 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002981 "device-id": f.deviceHandler.device.Id,
2982 "onu-geminfo": f.onuGemInfo[intfID],
2983 "intf-id": intfID,
2984 "gemport-id": gemPortID})
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002985
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302986 // get onuid from the onugem info cache
2987 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002988
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302989 for _, onu := range onugem {
2990 for _, gem := range onu.GemPorts {
2991 if gem == gemPortID {
2992 return onu.OnuID, nil
2993 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002994 }
2995 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002996 logger.Errorw(ctx, "onu-id-from-gem-port-not-found", log.Fields{
2997 "gem-port-id": gemPortID,
2998 "interface-id": intfID,
Kent Hagermane6ff1012020-07-14 15:07:53 -04002999 "all-gems-on-port": onugem,
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003000 })
Thomas Lee S94109f12020-03-03 16:39:29 +05303001 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003002 "interface-id": intfID,
3003 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00003004 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003005}
3006
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003007//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05303008func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003009 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003010 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003011 var err error
3012
3013 if packetIn.IntfType == "pon" {
3014 // packet indication does not have serial number , so sending as nil
Neha Sharma96b7bf22020-06-15 10:37:32 +00003015 if onuID, err = f.getOnuIDfromGemPortMap(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003016 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003017 return logicalPortNum, err
3018 }
3019 if packetIn.PortNo != 0 {
3020 logicalPortNum = packetIn.PortNo
3021 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003022 uniID := uint32(0) // FIXME - multi-uni support
Neha Sharma96b7bf22020-06-15 10:37:32 +00003023 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003024 }
3025 // 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 +00003026 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003027 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003028 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003029 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003030 logger.Infow(ctx, "retrieved-logicalport-from-packet-in",
Shrey Baid26912972020-04-16 21:02:31 +05303031 log.Fields{
3032 "logical-port-num": logicalPortNum,
3033 "intf-type": packetIn.IntfType,
3034 "packet": hex.EncodeToString(packetIn.Pkt),
3035 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003036 return logicalPortNum, nil
3037}
3038
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003039//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00003040func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003041 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00003042
3043 ctag, priority, err := getCTagFromPacket(ctx, packet)
3044 if err != nil {
3045 return 0, err
3046 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303047
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003048 f.onuGemInfoLock.RLock()
3049 defer f.onuGemInfoLock.RUnlock()
Esin Karaman7fb80c22020-07-16 14:23:33 +00003050 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003051 var ok bool
3052 gemPortID, ok = f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303053 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003054 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05303055 log.Fields{
3056 "pktinkey": pktInkey,
3057 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003058
3059 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003060 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303061 //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 +00003062 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303063 if err == nil {
3064 if gemPortID != 0 {
3065 f.packetInGemPort[pktInkey] = gemPortID
Neha Sharma96b7bf22020-06-15 10:37:32 +00003066 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05303067 log.Fields{
3068 "pktinkey": pktInkey,
3069 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303070 return gemPortID, nil
3071 }
3072 }
Shrey Baid26912972020-04-16 21:02:31 +05303073 return uint32(0), olterrors.NewErrNotFound("gem-port",
3074 log.Fields{
3075 "pktinkey": pktInkey,
3076 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003077
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003078}
3079
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003080// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303081func installFlowOnAllGemports(ctx context.Context,
3082 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003083 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003084 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05303085 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303086 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303087 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003088 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003089 args map[string]uint32,
3090 classifier map[string]interface{}, action map[string]interface{},
3091 logicalFlow *ofp.OfpFlowStats,
3092 gemPorts []uint32,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003093 TpInst interface{},
Manikkaraj kb1d51442019-07-23 10:41:02 -04003094 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00003095 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003096 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003097 vlanID ...uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003098 logger.Debugw(ctx, "installing-flow-on-all-gem-ports",
Shrey Baid26912972020-04-16 21:02:31 +05303099 log.Fields{
3100 "FlowType": FlowType,
3101 "gemPorts": gemPorts,
3102 "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05303103
Gamze Abaka724d0852020-03-18 12:10:24 +00003104 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
3105 // We need to trim prefix "0b", before further processing
3106 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
3107 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
3108
3109 // If a particular character in the string is set to '1', identify the index of this character from
3110 // the LSB position which marks the PCP bit consumed by the given gem port.
3111 // This PCP bit now becomes a classifier in the flow.
3112
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003113 switch TpInst := TpInst.(type) {
3114 case *tp.TechProfile:
3115 attributes := TpInst.DownstreamGemPortAttributeList
3116 if direction == Upstream {
3117 attributes = TpInst.UpstreamGemPortAttributeList
Gamze Abaka724d0852020-03-18 12:10:24 +00003118 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003119
3120 for _, gemPortAttribute := range attributes {
3121 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
3122 continue
Gamze Abaka724d0852020-03-18 12:10:24 +00003123 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003124 gemPortID := gemPortAttribute.GemportID
3125 if allPbitsMarked(gemPortAttribute.PbitMap) {
3126 classifier[VlanPcp] = uint32(VlanPCPMask)
3127 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003128 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3129 logger.Warn(ctx, err)
3130 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003131 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003132 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3133 logger.Warn(ctx, err)
3134 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003135 }
3136 } else {
3137 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
3138 if pbitSet == BinaryBit1 {
3139 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3140 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003141 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3142 logger.Warn(ctx, err)
3143 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003144 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003145 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3146 logger.Warn(ctx, err)
3147 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003148 }
3149 }
3150 }
3151 }
3152 }
3153 case *tp.EponProfile:
3154 if direction == Upstream {
3155 attributes := TpInst.UpstreamQueueAttributeList
3156 for _, queueAttribute := range attributes {
3157 gemPortID := queueAttribute.GemportID
3158 if allPbitsMarked(queueAttribute.PbitMap) {
3159 classifier[VlanPcp] = uint32(VlanPCPMask)
Gamze Abaka724d0852020-03-18 12:10:24 +00003160 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003161 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3162 logger.Warn(ctx, err)
3163 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003164 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003165 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3166 logger.Warn(ctx, err)
3167 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003168 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003169 } else {
3170 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3171 if pbitSet == BinaryBit1 {
3172 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3173 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003174 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3175 logger.Warn(ctx, err)
3176 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003177 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003178 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3179 logger.Warn(ctx, err)
3180 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003181 }
3182 }
3183 }
3184 }
3185 }
3186 } else {
3187 attributes := TpInst.DownstreamQueueAttributeList
3188 for _, queueAttribute := range attributes {
3189 gemPortID := queueAttribute.GemportID
3190 if allPbitsMarked(queueAttribute.PbitMap) {
3191 classifier[VlanPcp] = uint32(VlanPCPMask)
3192 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003193 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3194 logger.Warn(ctx, err)
3195 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003196 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003197 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3198 logger.Warn(ctx, err)
3199 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003200 }
3201 } else {
3202 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3203 if pbitSet == BinaryBit1 {
3204 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3205 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003206 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
3207 logger.Warn(ctx, err)
3208 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003209 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003210 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
3211 logger.Warn(ctx, err)
3212 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003213 }
3214 }
3215 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05303216 }
3217 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04003218 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003219 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003220 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpInst": TpInst})
Manikkaraj kb1d51442019-07-23 10:41:02 -04003221 }
3222}
3223
Gamze Abaka724d0852020-03-18 12:10:24 +00003224func allPbitsMarked(pbitMap string) bool {
3225 for pos, pBit := range pbitMap {
3226 if pos >= 2 && pBit != BinaryBit1 {
3227 return false
3228 }
3229 }
3230 return true
3231}
3232
David K. Bainbridge794735f2020-02-11 21:01:37 -08003233func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003234 logger.Debug(ctx, "adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003235 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003236 classifier[PacketTagType] = DoubleTag
3237 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003238 /* We manage flowId resource pool on per PON port basis.
3239 Since this situation is tricky, as a hack, we pass the NNI port
3240 index (network_intf_id) as PON port Index for the flowId resource
3241 pool. Also, there is no ONU Id available for trapping DHCP packets
3242 on NNI port, use onu_id as -1 (invalid)
3243 ****************** CAVEAT *******************
3244 This logic works if the NNI Port Id falls within the same valid
3245 range of PON Port Ids. If this doesn't work for some OLT Vendor
3246 we need to have a re-look at this.
3247 *********************************************
3248 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003249 onuID := -1
3250 uniID := -1
3251 gemPortID := -1
3252 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00003253 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303254 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303255 return olterrors.NewErrNotFound("nni-intreface-id",
3256 log.Fields{
3257 "classifier": classifier,
3258 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003259 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303260 }
3261
Neha Sharma96b7bf22020-06-15 10:37:32 +00003262 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303263 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003264 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003265 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003266 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003267 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003268 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303269 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id",
3270 log.Fields{
3271 "interface-id": networkInterfaceID,
3272 "onu-id": onuID,
3273 "uni-id": uniID,
3274 "gem-port-id": gemPortID,
3275 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003276 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003277 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003278 classifierProto, err := makeOpenOltClassifierField(classifier)
3279 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003280 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003281 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003282 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003283 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003284 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003285 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003286 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003287 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003288 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3289 OnuId: int32(onuID), // OnuId not required
3290 UniId: int32(uniID), // UniId not used
3291 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07003292 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003293 AllocId: int32(allocID), // AllocId not used
3294 NetworkIntfId: int32(networkInterfaceID),
3295 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003296 Classifier: classifierProto,
3297 Action: actionProto,
3298 Priority: int32(logicalFlow.Priority),
3299 Cookie: logicalFlow.Cookie,
3300 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003301 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003302 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003303 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003304 logger.Info(ctx, "dhcp-trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003305 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3306 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3307 int32(onuID),
3308 int32(uniID),
3309 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003310 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003311 }
3312 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003313}
salmansiddiqui7ac62132019-08-22 03:58:50 +00003314
Esin Karamanae41e2b2019-12-17 18:13:13 +00003315//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
3316func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
3317 var packetType string
3318 ovid, ivid := false, false
3319 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
3320 vid := vlanID & VlanvIDMask
3321 if vid != ReservedVlan {
3322 ovid = true
3323 }
3324 }
3325 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
3326 vid := uint32(metadata)
3327 if vid != ReservedVlan {
3328 ivid = true
3329 }
3330 }
3331 if ovid && ivid {
3332 packetType = DoubleTag
3333 } else if !ovid && !ivid {
3334 packetType = Untagged
3335 } else {
3336 packetType = SingleTag
3337 }
3338 return packetType
3339}
3340
3341//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08003342func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003343 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003344 action := make(map[string]interface{})
3345 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
3346 action[TrapToHost] = true
3347 /* We manage flowId resource pool on per PON port basis.
3348 Since this situation is tricky, as a hack, we pass the NNI port
3349 index (network_intf_id) as PON port Index for the flowId resource
3350 pool. Also, there is no ONU Id available for trapping packets
3351 on NNI port, use onu_id as -1 (invalid)
3352 ****************** CAVEAT *******************
3353 This logic works if the NNI Port Id falls within the same valid
3354 range of PON Port Ids. If this doesn't work for some OLT Vendor
3355 we need to have a re-look at this.
3356 *********************************************
3357 */
3358 onuID := -1
3359 uniID := -1
3360 gemPortID := -1
3361 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00003362 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003363 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303364 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003365 "classifier": classifier,
3366 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003367 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003368 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003369 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303370 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003371 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003372 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003373 }
npujarec5762e2020-01-01 14:08:48 +05303374 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003375 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303376 return olterrors.NewErrNotFound("igmp-flow-id",
3377 log.Fields{
3378 "interface-id": networkInterfaceID,
3379 "onu-id": onuID,
3380 "uni-id": uniID,
3381 "gem-port-id": gemPortID,
3382 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003383 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003384 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003385 classifierProto, err := makeOpenOltClassifierField(classifier)
3386 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003387 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003388 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003389 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003390 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003391 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003392 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003393 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003394 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003395 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3396 OnuId: int32(onuID), // OnuId not required
3397 UniId: int32(uniID), // UniId not used
3398 FlowId: flowID,
3399 FlowType: Downstream,
3400 AllocId: int32(allocID), // AllocId not used
3401 NetworkIntfId: int32(networkInterfaceID),
3402 GemportId: int32(gemPortID), // GemportId not used
3403 Classifier: classifierProto,
3404 Action: actionProto,
3405 Priority: int32(logicalFlow.Priority),
3406 Cookie: logicalFlow.Cookie,
3407 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003408 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003409 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003410 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003411 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003412 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3413 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3414 int32(onuID),
3415 int32(uniID),
3416 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003417 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003418 }
3419 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003420}
3421
salmansiddiqui7ac62132019-08-22 03:58:50 +00003422func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
3423 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05303424 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003425 }
3426 if Dir == tp_pb.Direction_UPSTREAM {
3427 return "upstream", nil
3428 } else if Dir == tp_pb.Direction_DOWNSTREAM {
3429 return "downstream", nil
3430 }
3431 return "", nil
3432}
3433
Kent Hagermane6ff1012020-07-14 15:07:53 -04003434// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303435func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003436 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003437 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00003438 var gemPort uint32
3439 intfID := args[IntfID]
3440 onuID := args[OnuID]
3441 uniID := args[UniID]
3442 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003443 allocID := args[AllocID]
salmansiddiqui7ac62132019-08-22 03:58:50 +00003444 if ipProto, ok := classifierInfo[IPProto]; ok {
3445 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003446 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003447 "tp-id": tpID,
3448 "alloc-id": allocID,
3449 "intf-id": intfID,
3450 "onu-id": onuID,
3451 "uni-id": uniID,
3452 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003453 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003454 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003455 tp_pb.Direction_UPSTREAM,
3456 pcp.(uint32))
3457 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00003458
Kent Hagermane6ff1012020-07-14 15:07:53 -04003459 if err := f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3460 logger.Warn(ctx, err)
3461 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003462 } else {
3463 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003464 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003465 }
3466
Girish Gowdra32625212020-04-29 11:26:35 -07003467 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003468 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05303469 log.Fields{
3470 "intf-id": intfID,
3471 "onu-id": onuID,
3472 "uni-id": uniID,
3473 "classifier-info:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003474 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003475 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
Esin Karamanae41e2b2019-12-17 18:13:13 +00003476 tp_pb.Direction_UPSTREAM,
3477 pcp.(uint32))
Kent Hagermane6ff1012020-07-14 15:07:53 -04003478 if err := f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3479 logger.Warn(ctx, err)
3480 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00003481 } else {
3482 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003483 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003484 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003485 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003486 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003487 return
3488 }
3489 } else if ethType, ok := classifierInfo[EthType]; ok {
3490 if ethType.(uint32) == EapEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003491 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003492 "intf-id": intfID,
3493 "onu-id": onuID,
3494 "uni-id": uniID,
3495 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003496 var vlanID uint32
3497 if val, ok := classifierInfo[VlanVid]; ok {
3498 vlanID = (val.(uint32)) & VlanvIDMask
3499 } else {
3500 vlanID = DefaultMgmtVlan
3501 }
3502 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003503 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003504 tp_pb.Direction_UPSTREAM,
3505 pcp.(uint32))
3506
Kent Hagermane6ff1012020-07-14 15:07:53 -04003507 if err := f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID); err != nil {
3508 logger.Warn(ctx, err)
3509 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003510 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003511 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003512 }
3513 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003514 } else if _, ok := actionInfo[PushVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003515 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003516 "intf-id": intfID,
3517 "onu-id": onuID,
3518 "uni-id": uniID,
3519 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003520 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003521 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003522 tp_pb.Direction_UPSTREAM,
3523 pcp.(uint32))
3524 //Adding HSIA upstream flow
Kent Hagermane6ff1012020-07-14 15:07:53 -04003525 if err := f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3526 logger.Warn(ctx, err)
3527 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003528 } else {
3529 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003530 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003531 }
3532 } else if _, ok := actionInfo[PopVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003533 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003534 "intf-id": intfID,
3535 "onu-id": onuID,
3536 "uni-id": uniID,
3537 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003538 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003539 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05003540 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003541 pcp.(uint32))
3542 //Adding HSIA downstream flow
Kent Hagermane6ff1012020-07-14 15:07:53 -04003543 if err := f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3544 logger.Warn(ctx, err)
3545 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003546 } else {
3547 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003548 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003549 }
3550 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003551 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05303552 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003553 "intf-id": intfID,
3554 "onu-id": onuID,
3555 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05303556 "classifier": classifierInfo,
3557 "action": actionInfo,
3558 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003559 return
3560 }
3561 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04003562 go func() {
3563 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
3564 logger.Warn(ctx, err)
3565 }
3566 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003567}
3568
Gamze Abakafee36392019-10-03 11:17:24 +00003569func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
3570 flowIDList := f.flowsUsedByGemPort[gemPK]
Kent Hagermane6ff1012020-07-14 15:07:53 -04003571 return len(flowIDList) > 1
Gamze Abakafee36392019-10-03 11:17:24 +00003572}
3573
npujarec5762e2020-01-01 14:08:48 +05303574func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3575 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003576 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3577 for _, currentGemPort := range currentGemPorts {
3578 for _, tpGemPort := range tpGemPorts {
3579 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3580 return true, currentGemPort
3581 }
3582 }
3583 }
Girish Gowdra54934262019-11-13 14:19:55 +05303584 if tpInst.InstanceCtrl.Onu == "single-instance" {
3585 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Kent Hagermane6ff1012020-07-14 15:07:53 -04003586 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID); err != nil {
3587 logger.Warn(ctx, err)
3588 }
3589 if err := f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
3590 logger.Warn(ctx, err)
3591 }
Girish Gowdra54934262019-11-13 14:19:55 +05303592
3593 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3594 // still be used on other uni ports.
3595 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3596 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003597 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003598 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303599 for i := 0; i < len(tpInstances); i++ {
3600 tpI := tpInstances[i]
3601 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303602 for _, tpGemPort := range tpGemPorts {
3603 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003604 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303605 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303606 }
3607 }
3608 }
3609 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003610 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003611 return false, 0
3612}
3613
Neha Sharma96b7bf22020-06-15 10:37:32 +00003614func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003615 for _, field := range flows.GetOfbFields(flow) {
3616 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003617 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003618 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003619 } else if field.Type == flows.ETH_DST {
3620 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003621 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003622 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003623 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003624 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003625 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003626 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003627 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003628 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303629 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003630 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003631 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003632 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003633 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003634 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003635 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003636 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003637 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003638 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003639 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003640 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003641 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003642 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003643 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003644 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003645 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003646 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003647 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003648 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003649 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003650 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003651 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003652 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003653 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003654 return
3655 }
3656 }
3657}
3658
Neha Sharma96b7bf22020-06-15 10:37:32 +00003659func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003660 for _, action := range flows.GetActions(flow) {
3661 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003662 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003663 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003664 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003665 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003666 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003667 }
Scott Baker355d1742019-10-24 10:57:52 -07003668 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003669 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003670 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003671 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003672 if out := action.GetPush(); out != nil {
3673 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003674 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003675 } else {
3676 actionInfo[PushVlan] = true
3677 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003678 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303679 log.Fields{
3680 "push-tpid": actionInfo[TPID].(uint32),
3681 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003682 }
3683 }
Scott Baker355d1742019-10-24 10:57:52 -07003684 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003685 if out := action.GetSetField(); out != nil {
3686 if field := out.GetField(); field != nil {
3687 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003688 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003689 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003690 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3691 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003692 }
3693 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003694 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003695 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003696 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003697 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003698 }
3699 }
3700 return nil
3701}
3702
Neha Sharma96b7bf22020-06-15 10:37:32 +00003703func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003704 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003705 fieldtype := ofbField.GetType()
3706 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003707 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3708 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003709 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003710 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003711 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003712 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003713 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3714 pcp := ofbField.GetVlanPcp()
3715 actionInfo[VlanPcp] = pcp
3716 log.Debugw("action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003717 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003718 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003719 }
3720 }
3721}
3722
Neha Sharma96b7bf22020-06-15 10:37:32 +00003723func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003724 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003725 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003726 } else {
3727 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003728 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003729 }
3730}
3731
Neha Sharma96b7bf22020-06-15 10:37:32 +00003732func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003733 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003734 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003735 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3736 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003737 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003738 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003739 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303740 log.Fields{
3741 "newinport": classifierInfo[InPort].(uint32),
3742 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003743 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303744 return olterrors.NewErrNotFound("child-in-port",
3745 log.Fields{
3746 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3747 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003748 }
3749 }
3750 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003751 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003752 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003753 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003754 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003755 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003756 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303757 log.Fields{
3758 "newoutport": actionInfo[Output].(uint32),
3759 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003760 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303761 return olterrors.NewErrNotFound("out-port",
3762 log.Fields{
3763 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3764 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003765 }
3766 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3767 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003768 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003769 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003770 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303771 log.Fields{
3772 "newinport": actionInfo[Output].(uint32),
3773 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003774 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303775 return olterrors.NewErrNotFound("nni-port",
3776 log.Fields{
3777 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3778 "in-port": classifierInfo[InPort].(uint32),
3779 "out-port": actionInfo[Output].(uint32),
3780 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003781 }
3782 }
3783 }
3784 return nil
3785}
Gamze Abakafee36392019-10-03 11:17:24 +00003786
Neha Sharma96b7bf22020-06-15 10:37:32 +00003787func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003788 /* Metadata 8 bytes:
3789 Most Significant 2 Bytes = Inner VLAN
3790 Next 2 Bytes = Tech Profile ID(TPID)
3791 Least Significant 4 Bytes = Port ID
3792 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3793 subscriber related flows.
3794 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003795 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003796 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003797 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003798 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003799 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003800 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003801}
3802
3803func appendUnique(slice []uint32, item uint32) []uint32 {
3804 for _, sliceElement := range slice {
3805 if sliceElement == item {
3806 return slice
3807 }
3808 }
3809 return append(slice, item)
3810}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303811
3812// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003813func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303814
3815 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3816 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003817 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003818 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003819 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003820 log.Fields{
3821 "port-number": action[Output].(uint32),
3822 "error": err})
3823 return uint32(0), err
3824 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003825 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303826 return intfID, nil
3827 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003828 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003829 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003830 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003831 log.Fields{
3832 "port-number": action[Output].(uint32),
3833 "error": err})
3834 return uint32(0), err
3835 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003836 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303837 return intfID, nil
3838 }
3839 return uint32(0), nil
3840}
3841
3842// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003843func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3844 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3845 if err != nil {
3846 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3847 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3848 return
3849 }
3850 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003851
3852 f.onuGemInfoLock.Lock()
3853 defer f.onuGemInfoLock.Unlock()
3854
Matt Jeanneret1719a072019-12-20 14:50:14 -05003855 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303856 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003857 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003858 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 +05303859 log.Fields{
3860 "pktinkey": pktInkey,
3861 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003862 return
3863 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303864 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003865 f.packetInGemPort[pktInkey] = gemPort
3866
npujarec5762e2020-01-01 14:08:48 +05303867 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003868 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 +05303869 log.Fields{
3870 "pktinkey": pktInkey,
3871 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303872}
3873
Esin Karaman7fb80c22020-07-16 14:23:33 +00003874//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3875func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3876 if packet == nil || len(packet) < 18 {
3877 log.Error("unable-get-c-tag-from-the-packet--invalid-packet-length ")
3878 return 0, 0, errors.New("invalid packet length")
3879 }
3880 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3881 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3882
3883 var index int8
3884 if outerEthType == 0x8100 {
3885 if innerEthType == 0x8100 {
3886 // q-in-q 802.1ad or 802.1q double tagged packet.
3887 // get the inner vlanId
3888 index = 18
3889 } else {
3890 index = 14
3891 }
3892 priority := (packet[index] >> 5) & 0x7
3893 //13 bits composes vlanId value
3894 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3895 return vlan, priority, nil
3896 }
3897 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3898 return 0, 0, nil
3899}
3900
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303901// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303902func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003903
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003904 f.onuGemInfoLock.Lock()
3905 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003906
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303907 onugem := f.onuGemInfo[intfID]
3908 for idx, onu := range onugem {
3909 if onu.OnuID == onuID {
3910 for _, uni := range onu.UniPorts {
3911 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003912 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 +05303913 return
3914 }
3915 }
3916 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3917 f.onuGemInfo[intfID] = onugem
3918 }
3919 }
npujarec5762e2020-01-01 14:08:48 +05303920 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003921
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303922}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303923
npujarec5762e2020-01-01 14:08:48 +05303924func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3925 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303926 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003927 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303928 return
3929 }
3930 for gem, FlowIDs := range flowIDsList {
3931 gemPK := gemPortKey{intf, uint32(gem)}
3932 f.flowsUsedByGemPort[gemPK] = FlowIDs
3933 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303934}
Esin Karamanccb714b2019-11-29 15:02:06 +00003935
3936//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
3937//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05303938func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
3939 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00003940 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003941 logger.Error(ctx, "failed-to-get-pon-interface-to-multicast-queue-map")
Esin Karamanccb714b2019-11-29 15:02:06 +00003942 return
3943 }
3944 for intf, queueInfo := range storedMulticastQueueMap {
3945 q := queueInfoBrief{
3946 gemPortID: queueInfo[0],
3947 servicePriority: queueInfo[1],
3948 }
3949 f.interfaceToMcastQueueMap[intf] = &q
3950 }
3951}
3952
3953//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
3954//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
3955//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05303956func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
3957 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00003958 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003959 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00003960 }
3961 if exists {
3962 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
3963 }
3964 return nil, exists, nil
3965}
3966
3967func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
3968 groupDesc := ofp.OfpGroupDesc{
3969 Type: ofp.OfpGroupType_OFPGT_ALL,
3970 GroupId: groupID,
3971 }
3972 groupEntry := ofp.OfpGroupEntry{
3973 Desc: &groupDesc,
3974 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003975 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003976 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00003977 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003978 bucket := ofp.OfpBucket{
3979 Actions: acts,
3980 }
3981 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00003982 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003983 return &groupEntry
3984}