blob: 964025112b3d370673658462814a80062d805af2 [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
22 "crypto/md5"
Matteo Scandolo6056e822019-11-13 14:05:29 -080023 "encoding/hex"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "encoding/json"
Girish Gowdracefae192020-03-19 18:14:10 -070025 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053026 "fmt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040027 "math/big"
Girish Gowdrafae935c2020-02-17 19:21:44 +053028 "strings"
William Kurkian740a09c2019-10-23 17:07:38 -040029 "sync"
Girish Gowdra3d633032019-12-10 16:37:05 +053030 "time"
Manikkaraj kb1d51442019-07-23 10:41:02 -040031
Esin Karamanccb714b2019-11-29 15:02:06 +000032 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v3/pkg/log"
34 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080035 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000036 "github.com/opencord/voltha-protos/v3/go/common"
37 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
38 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
39 openoltpb2 "github.com/opencord/voltha-protos/v3/go/openolt"
40 tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
41 "github.com/opencord/voltha-protos/v3/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040042
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040043 //deepcopy "github.com/getlantern/deepcopy"
Girish Gowdra3d633032019-12-10 16:37:05 +053044 "github.com/EagleChen/mapmutex"
Thomas Lee S94109f12020-03-03 16:39:29 +053045 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000046 "google.golang.org/grpc/codes"
47 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053048)
49
50const (
51 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070053 //HsiaFlow flow category
54 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053055
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070056 //EapolFlow flow category
57 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053058
Manikkaraj kb1d51442019-07-23 10:41:02 -040059 //DhcpFlow flow category
60 DhcpFlow = "DHCP_FLOW"
61
Esin Karamanccb714b2019-11-29 15:02:06 +000062 //MulticastFlow flow category
63 MulticastFlow = "MULTICAST_FLOW"
64
Esin Karamanae41e2b2019-12-17 18:13:13 +000065 //IgmpFlow flow category
66 IgmpFlow = "IGMP_FLOW"
67
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068 //IPProtoDhcp flow category
69 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053070
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070071 //IPProtoIgmp flow category
72 IPProtoIgmp = 2
73
74 //EapEthType eapethtype value
75 EapEthType = 0x888e
76 //LldpEthType lldp ethtype value
77 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000078 //IPv4EthType IPv4 ethernet type value
79 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070080
81 //IgmpProto proto value
82 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053083
Andrea Campanella7acc0b92020-02-14 09:20:49 +010084 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
85 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040086
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087 //DefaultMgmtVlan default vlan value
88 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053089
manikkaraj kbf256be2019-03-25 00:13:48 +053090 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070091
David K. Bainbridge82efc492019-09-04 09:57:11 -070092 //Upstream constant
93 Upstream = "upstream"
94 //Downstream constant
95 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000096 //Multicast constant
97 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070098 //PacketTagType constant
99 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700100 //Untagged constant
101 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700102 //SingleTag constant
103 SingleTag = "single_tag"
104 //DoubleTag constant
105 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +0530106
107 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108
109 //EthType constant
110 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +0000111 //EthDst constant
112 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113 //TPID constant
114 TPID = "tpid"
115 //IPProto constant
116 IPProto = "ip_proto"
117 //InPort constant
118 InPort = "in_port"
119 //VlanVid constant
120 VlanVid = "vlan_vid"
121 //VlanPcp constant
122 VlanPcp = "vlan_pcp"
123
124 //UDPDst constant
125 UDPDst = "udp_dst"
126 //UDPSrc constant
127 UDPSrc = "udp_src"
128 //Ipv4Dst constant
129 Ipv4Dst = "ipv4_dst"
130 //Ipv4Src constant
131 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700132 //Metadata constant
133 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700134 //TunnelID constant
135 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700136 //Output constant
137 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000138 //GroupID constant
139 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700140 // Actions
141
142 //PopVlan constant
143 PopVlan = "pop_vlan"
144 //PushVlan constant
145 PushVlan = "push_vlan"
146 //TrapToHost constant
147 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400148 //MaxMeterBand constant
149 MaxMeterBand = 2
150 //VlanPCPMask contant
151 VlanPCPMask = 0xFF
152 //VlanvIDMask constant
153 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000154 //IntfID constant
155 IntfID = "intfId"
156 //OnuID constant
157 OnuID = "onuId"
158 //UniID constant
159 UniID = "uniId"
160 //PortNo constant
161 PortNo = "portNo"
162 //AllocID constant
163 AllocID = "allocId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000164
165 //NoneOnuID constant
166 NoneOnuID = -1
167 //NoneUniID constant
168 NoneUniID = -1
169 //NoneGemPortID constant
170 NoneGemPortID = -1
Girish Gowdrafae935c2020-02-17 19:21:44 +0530171
172 // BinaryStringPrefix is binary string prefix
173 BinaryStringPrefix = "0b"
174 // BinaryBit1 is binary bit 1 expressed as a character
175 BinaryBit1 = '1'
manikkaraj kbf256be2019-03-25 00:13:48 +0530176)
177
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400178type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700179 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400180 gemPort uint32
181}
182
Girish Gowdra3d633032019-12-10 16:37:05 +0530183type pendingFlowDeleteKey struct {
184 intfID uint32
185 onuID uint32
186 uniID uint32
187}
188
189type tpLockKey struct {
190 intfID uint32
191 onuID uint32
192 uniID uint32
193}
194
Gamze Abakafee36392019-10-03 11:17:24 +0000195type schedQueue struct {
196 direction tp_pb.Direction
197 intfID uint32
198 onuID uint32
199 uniID uint32
200 tpID uint32
201 uniPort uint32
202 tpInst *tp.TechProfile
203 meterID uint32
204 flowMetadata *voltha.FlowMetadata
205}
206
Esin Karamanccb714b2019-11-29 15:02:06 +0000207type queueInfoBrief struct {
208 gemPortID uint32
209 servicePriority uint32
210}
211
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700212//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530213type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000214 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000215 deviceHandler *DeviceHandler
216 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000217 onuIdsLock sync.RWMutex
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530218 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
219 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
220 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
221 lockCache sync.RWMutex
Girish Gowdra3d633032019-12-10 16:37:05 +0530222 pendingFlowDelete sync.Map
223 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Esin Karamanccb714b2019-11-29 15:02:06 +0000224 perUserFlowHandleLock *mapmutex.Mutex
225 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 +0530226}
227
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700228//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
npujarec5762e2020-01-01 14:08:48 +0530229func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700230 logger.Infow("Initializing flow manager", log.Fields{"deviceId": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530231 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530232 var err error
233 var idx uint32
234
manikkaraj kbf256be2019-03-25 00:13:48 +0530235 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530236 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000237 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530238 if err = flowMgr.populateTechProfilePerPonPort(); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000239 logger.Errorw("Error while populating tech profile mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530240 return nil
241 }
William Kurkian740a09c2019-10-23 17:07:38 -0400242 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530243 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
244 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
245 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo)
246 ponPorts := rMgr.DevInfo.GetPonPorts()
247 //Load the onugem info cache from kv store on flowmanager start
248 for idx = 0; idx < ponPorts; idx++ {
npujarec5762e2020-01-01 14:08:48 +0530249 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000250 logger.Error("Failed to load onu gem info cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530251 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530252 //Load flowID list per gem map per interface from the kvstore.
npujarec5762e2020-01-01 14:08:48 +0530253 flowMgr.loadFlowIDlistForGem(ctx, idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530254 }
255 flowMgr.lockCache = sync.RWMutex{}
Girish Gowdra3d633032019-12-10 16:37:05 +0530256 flowMgr.pendingFlowDelete = sync.Map{}
Girish Gowdrab77ded92020-04-08 11:45:05 -0700257 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(300, 100000000, 10000000, 1.1, 0.2)
Esin Karamanccb714b2019-11-29 15:02:06 +0000258 flowMgr.interfaceToMcastQueueMap = make(map[uint32]*queueInfoBrief)
259 //load interface to multicast queue map from kv store
npujarec5762e2020-01-01 14:08:48 +0530260 flowMgr.loadInterfaceToMulticastQueueMap(ctx)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000261 logger.Info("Initialization of flow manager success!!")
manikkaraj kbf256be2019-03-25 00:13:48 +0530262 return &flowMgr
263}
264
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700265func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700266 if direction == Upstream {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000267 logger.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700268 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700269 } else if direction == Downstream {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000270 logger.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700271 return uint64(flowID), nil
Esin Karamanccb714b2019-11-29 15:02:06 +0000272 } else if direction == Multicast {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000273 logger.Debug("multicast flow, shifting id")
Esin Karamanccb714b2019-11-29 15:02:06 +0000274 return 0x2<<15 | uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400275 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530276 return 0, olterrors.NewErrInvalidValue(log.Fields{"direction": direction}, nil).Log()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400277 }
278}
279
npujarec5762e2020-01-01 14:08:48 +0530280func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000281 logger.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700282 log.Fields{"device": f.deviceHandler.deviceID})
Gamze Abakafee36392019-10-03 11:17:24 +0000283 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
284 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
285 if !ok {
286 flowIDList = []uint32{deviceFlow.FlowId}
287 }
288 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
289 f.flowsUsedByGemPort[gemPK] = flowIDList
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530290 // update the flowids for a gem to the KVstore
npujarec5762e2020-01-01 14:08:48 +0530291 f.resourceMgr.UpdateFlowIDsForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400292}
293
npujarec5762e2020-01-01 14:08:48 +0530294func (f *OpenOltFlowMgr) divideAndAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000295 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
296 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000297 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530298 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400299 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530300
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700301 logger.Infow("dividing-flow", log.Fields{
302 "deviceId": f.deviceHandler.device.Id,
303 "intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
304 "classifier": classifierInfo,
305 "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400306 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
307 // is because the flow is an NNI flow and there would be no onu resources associated with it
308 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400309 if onuID <= 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000310 logger.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
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))
315 logger.Debugw("uni-port-path", log.Fields{"uni": uni, "deviceId": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530316
317 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
318 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700319 logger.Debugw("dividing-flow-create-tcont-gem-ports", log.Fields{
320 "deviceId": f.deviceHandler.device.Id,
321 "intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
322 "classifier": classifierInfo,
323 "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
npujarec5762e2020-01-01 14:08:48 +0530324 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530325 if allocID == 0 || gemPorts == nil || TpInst == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000326 logger.Error("alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530327 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
328 return
329 }
330 args := make(map[string]uint32)
331 args[IntfID] = intfID
332 args[OnuID] = onuID
333 args[UniID] = uniID
334 args[PortNo] = portNo
335 args[AllocID] = allocID
336
337 /* Flows can be added specific to gemport if p-bits are received.
338 * If no pbit mentioned then adding flows for all gemports
339 */
npujarec5762e2020-01-01 14:08:48 +0530340 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530341 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
342 } else {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700343 logger.Errorw("failed-to-acquire-per-user-flow-handle-lock",
Girish Gowdra3d633032019-12-10 16:37:05 +0530344 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400345 return
346 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530347}
348
salmansiddiqui7ac62132019-08-22 03:58:50 +0000349// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530350func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400351
Girish Kumar2ad402b2020-03-20 19:45:12 +0000352 logger.Debugw("CreateSchedulerQueues", log.Fields{"Dir": sq.direction, "IntfID": sq.intfID,
Gamze Abakafee36392019-10-03 11:17:24 +0000353 "OnuID": sq.onuID, "UniID": sq.uniID, "TpID": sq.tpID, "MeterID": sq.meterID,
354 "TpInst": sq.tpInst, "flowMetadata": sq.flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400355
Gamze Abakafee36392019-10-03 11:17:24 +0000356 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000357 if err != nil {
358 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400359 }
360
361 /* Lets make a simple assumption that if the meter-id is present on the KV store,
362 * then the scheduler and queues configuration is applied on the OLT device
363 * in the given direction.
364 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000365
Manikkaraj kb1d51442019-07-23 10:41:02 -0400366 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530367 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400368 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000369 return olterrors.NewErrNotFound("meter", log.Fields{"intfId": sq.intfID, "onuId": sq.onuID, "uniId": sq.uniID}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400370 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000371
Manikkaraj kb1d51442019-07-23 10:41:02 -0400372 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000373 if KvStoreMeter.MeterId == sq.meterID {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000374 logger.Debug("Scheduler already created for upstream")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400375 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400376 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530377 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800378 "unsupported": "meter-id",
379 "kv-store-meter-id": KvStoreMeter.MeterId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000380 "meter-id-in-flow": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400381 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000382
Girish Kumar2ad402b2020-03-20 19:45:12 +0000383 logger.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": sq.meterID, "Direction": Direction})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000384
Gamze Abakafee36392019-10-03 11:17:24 +0000385 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000386 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Gamze Abakafee36392019-10-03 11:17:24 +0000387 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000388 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400389 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000390
391 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000392 return olterrors.NewErrNotFound("scheduler-config", log.Fields{"IntfID": sq.intfID, "Direction": sq.direction, "tpInst": sq.tpInst}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000393 }
394
Manikkaraj kb1d51442019-07-23 10:41:02 -0400395 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000396 if sq.flowMetadata != nil {
397 for _, meter := range sq.flowMetadata.Meters {
398 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400399 meterConfig = meter
Girish Kumar2ad402b2020-03-20 19:45:12 +0000400 logger.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401 break
402 }
403 }
404 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000405 logger.Error("Flow-metadata-is-not-present-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400406 }
407 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530408 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800409 "reason": "Could-not-get-meterbands-from-flowMetadata",
410 "flow-metadata": sq.flowMetadata,
Girish Kumarf26e4882020-03-05 06:49:10 +0000411 "meter-id": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400412 } else if len(meterConfig.Bands) < MaxMeterBand {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000413 logger.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": sq.meterID})
Thomas Lee S94109f12020-03-03 16:39:29 +0530414 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800415 "reason": "Invalid-number-of-bands-in-meter",
416 "meterband-count": len(meterConfig.Bands),
417 "metabands": meterConfig.Bands,
Girish Kumarf26e4882020-03-05 06:49:10 +0000418 "meter-id": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400419 }
420 cir := meterConfig.Bands[0].Rate
421 cbs := meterConfig.Bands[0].BurstSize
422 eir := meterConfig.Bands[1].Rate
423 ebs := meterConfig.Bands[1].BurstSize
424 pir := cir + eir
425 pbs := cbs + ebs
426 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
427
Gamze Abakafee36392019-10-03 11:17:24 +0000428 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400429
npujarec5762e2020-01-01 14:08:48 +0530430 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000431 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device", log.Fields{"intfID": sq.intfID, "direction": sq.direction}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 }
433
salmansiddiqui7ac62132019-08-22 03:58:50 +0000434 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400435 * store the meter id on the KV store, for further reference.
436 */
npujarec5762e2020-01-01 14:08:48 +0530437 if err := f.resourceMgr.UpdateMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000438 return olterrors.NewErrAdapter("failed-updating-meter-id", log.Fields{"onu-id": sq.onuID, "meter-id": sq.meterID}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400439 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000440 logger.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400441 "Meter": meterConfig})
442 return nil
443}
444
npujarec5762e2020-01-01 14:08:48 +0530445func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000446
447 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
448
449 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000450 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration", log.Fields{"intfID": sq.intfID, "direction": sq.direction}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000451 }
452
Girish Kumar2ad402b2020-03-20 19:45:12 +0000453 logger.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": sq.direction, "TrafficScheds": TrafficSched})
npujarec5762e2020-01-01 14:08:48 +0530454 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000455 IntfId: sq.intfID, OnuId: sq.onuID,
456 UniId: sq.uniID, PortNo: sq.uniPort,
457 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000458 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000459 }
460
461 // On receiving the CreateTrafficQueues request, the driver should create corresponding
462 // downstream queues.
Girish Kumar2ad402b2020-03-20 19:45:12 +0000463 logger.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": sq.direction, "TrafficQueues": trafficQueues})
npujarec5762e2020-01-01 14:08:48 +0530464 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000465 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
466 UniId: sq.uniID, PortNo: sq.uniPort,
467 TrafficQueues: trafficQueues}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000468 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"TrafficQueues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000469 }
470
Esin Karamanccb714b2019-11-29 15:02:06 +0000471 if sq.direction == tp_pb.Direction_DOWNSTREAM {
472 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(sq.tpInst)
473 if len(multicastTrafficQueues) > 0 {
474 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
475 //assumed that there is only one queue per PON for the multicast service
476 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
477 //just put it in interfaceToMcastQueueMap to use for building group members
478 multicastQueuePerPonPort := multicastTrafficQueues[0]
479 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
480 gemPortID: multicastQueuePerPonPort.GemportId,
481 servicePriority: multicastQueuePerPonPort.Priority,
482 }
483 //also store the queue info in kv store
npujarec5762e2020-01-01 14:08:48 +0530484 f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID,
Esin Karamanccb714b2019-11-29 15:02:06 +0000485 multicastQueuePerPonPort.GemportId,
486 multicastQueuePerPonPort.Priority)
487 }
488 }
489 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000490 return nil
491}
492
salmansiddiqui7ac62132019-08-22 03:58:50 +0000493// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530494func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400495
496 var Direction string
497 var SchedCfg *tp_pb.SchedulerConfig
498 var err error
Girish Kumar2ad402b2020-03-20 19:45:12 +0000499 logger.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": sq.direction, "IntfID": sq.intfID,
Gamze Abakafee36392019-10-03 11:17:24 +0000500 "OnuID": sq.onuID, "UniID": sq.uniID, "UniPort": sq.uniPort})
501 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000502 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000504 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000505 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400506 Direction = "downstream"
507 }
508
Girish Kumar8f73fe02019-12-09 13:19:37 +0000509 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000510 return olterrors.NewErrNotFound("scheduler-config", log.Fields{"IntID": sq.intfID, "Direction": sq.direction}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000511 }
512
npujarec5762e2020-01-01 14:08:48 +0530513 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400514 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000515 return olterrors.NewErrNotFound("meter", log.Fields{"onuID": sq.onuID}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400516 }
517 if KVStoreMeter == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000518 logger.Debugw("No-meter-has-been-installed-yet", log.Fields{"direction": Direction, "IntfID": sq.intfID, "OnuID": sq.onuID, "UniID": sq.uniID})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400519 return nil
520 }
521 cir := KVStoreMeter.Bands[0].Rate
522 cbs := KVStoreMeter.Bands[0].BurstSize
523 eir := KVStoreMeter.Bands[1].Rate
524 ebs := KVStoreMeter.Bands[1].BurstSize
525 pir := cir + eir
526 pbs := cbs + ebs
527
528 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
529
Gamze Abakafee36392019-10-03 11:17:24 +0000530 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Girish Kumar8f73fe02019-12-09 13:19:37 +0000531
532 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
533 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000534 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration", log.Fields{"intfID": sq.intfID, "direction": sq.direction}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000535 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400536
npujarec5762e2020-01-01 14:08:48 +0530537 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000538 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
539 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400540 TrafficQueues: TrafficQueues}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000541 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
542 log.Fields{"intfID": sq.intfID, "TrafficQueues": TrafficQueues}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400543 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000544 logger.Debug("Removed traffic queues successfully")
npujarec5762e2020-01-01 14:08:48 +0530545 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000546 IntfId: sq.intfID, OnuId: sq.onuID,
547 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400548 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000549 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
550 log.Fields{"intfID": sq.intfID, "TrafficSchedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400551 }
552
Girish Kumar2ad402b2020-03-20 19:45:12 +0000553 logger.Debug("Removed traffic schedulers successfully")
salmansiddiqui7ac62132019-08-22 03:58:50 +0000554
555 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400556 * delete the meter id on the KV store.
557 */
npujarec5762e2020-01-01 14:08:48 +0530558 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400559 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000560 return olterrors.NewErrAdapter("unable-to-remove-meter", log.Fields{"onu": sq.onuID, "meter": KVStoreMeter.MeterId}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400561 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000562 logger.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400563 return err
564}
565
Gamze Abakafee36392019-10-03 11:17:24 +0000566// This function allocates tconts and GEM ports for an ONU
npujarec5762e2020-01-01 14:08:48 +0530567func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) (uint32, []uint32, *tp.TechProfile) {
Gamze Abakafee36392019-10-03 11:17:24 +0000568 var allocIDs []uint32
569 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530570 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530571 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000572 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000573
npujarec5762e2020-01-01 14:08:48 +0530574 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
575 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400576
577 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530578
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700579 logger.Infow("creating-new-tcont-and-gem", log.Fields{
580 "pon": intfID, "onu": onuID, "uni": uniID,
581 "deviceId": f.deviceHandler.device.Id, "tpId": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530582
Manikkaraj kb1d51442019-07-23 10:41:02 -0400583 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530584 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000585 if techProfileInstance == nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700586 logger.Infow("tp-instance-not-found--creating-new", log.Fields{"path": tpPath, "deviceId": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530587 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000588 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530589 // This should not happen, something wrong in KV backend transaction
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700590 logger.Errorw("tp-instance-create-failed", log.Fields{"error": err, "tpID": TpID, "deviceId": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000591 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530592 }
npujarec5762e2020-01-01 14:08:48 +0530593 f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530594 } else {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700595 logger.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni, "deviceId": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530596 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530597 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400598 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000599 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
600 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530601 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700602 logger.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID, "deviceId": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000603 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400604 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530605 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400606 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000607 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
608 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530609 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700610 logger.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID, "deviceId": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000611 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400612 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530613 }
Gamze Abakafee36392019-10-03 11:17:24 +0000614
615 allocID := techProfileInstance.UsScheduler.AllocID
Gamze Abakafee36392019-10-03 11:17:24 +0000616 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Gamze Abakafee36392019-10-03 11:17:24 +0000617 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400618 }
Gamze Abakafee36392019-10-03 11:17:24 +0000619
Girish Gowdra3d633032019-12-10 16:37:05 +0530620 if tpInstanceExists {
621 return allocID, gemPortIDs, techProfileInstance
622 }
623
624 allocIDs = appendUnique(allocIDs, allocID)
625 for _, gemPortID := range gemPortIDs {
626 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
627 }
628
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700629 logger.Debugw("allocated-tcont-and-GEM-ports", log.Fields{"allocIDs": allocIDs, "gemports": allgemPortIDs, "deviceId": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530630 // Send Tconts and GEM ports to KV store
npujarec5762e2020-01-01 14:08:48 +0530631 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000632 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530633}
634
npujarec5762e2020-01-01 14:08:48 +0530635func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530636
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700637 logger.Debugw("storing-allocated-Tconts-and-GEM-ports-into-KV-store",
638 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs, "deviceId": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530639 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530640 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000641 logger.Error("Errow while uploading allocID to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530642 }
npujarec5762e2020-01-01 14:08:48 +0530643 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000644 logger.Error("Errow while uploading GEMports to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530645 }
npujarec5762e2020-01-01 14:08:48 +0530646 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000647 logger.Error("Errow while uploading gemtopon map to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530648 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700649 logger.Debugw("stored-tconts-and-GEM-into-KV-store-successfully", log.Fields{"deviceId": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400650 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530651 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400652 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530653}
654
655func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000656 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530657 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000658 for _, intfID := range techRange.IntfIds {
659 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400660 tpCount++
Girish Kumar2ad402b2020-03-20 19:45:12 +0000661 logger.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530662 }
663 }
664 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400665 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530666 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800667 "reason": "TP count does not match number of PON ports",
668 "tech-profile-count": tpCount,
Girish Kumarf26e4882020-03-05 06:49:10 +0000669 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts()}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530670 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000671 logger.Infow("Populated techprofile for ponports successfully",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400672 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530673 return nil
674}
675
npujarec5762e2020-01-01 14:08:48 +0530676func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530677 portNo uint32, uplinkClassifier map[string]interface{},
678 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800679 allocID uint32, gemportID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700680 uplinkClassifier[PacketTagType] = SingleTag
Girish Kumar2ad402b2020-03-20 19:45:12 +0000681 logger.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800682 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700683 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530684 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530685}
686
npujarec5762e2020-01-01 14:08:48 +0530687func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530688 portNo uint32, downlinkClassifier map[string]interface{},
689 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800690 allocID uint32, gemportID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700691 downlinkClassifier[PacketTagType] = DoubleTag
Girish Kumar2ad402b2020-03-20 19:45:12 +0000692 logger.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
Manikkaraj k884c1242019-04-11 16:26:42 +0530693 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400694 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
695 if vlan, exists := downlinkClassifier[VlanVid]; exists {
696 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700697 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400698 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000699 logger.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800700 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400701 }
702 }
703 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530704 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400705
Manikkaraj k884c1242019-04-11 16:26:42 +0530706 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700707 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400708 // vlan_vid is a uint32. must be type asserted as such or conversion fails
709 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530710 if ok {
711 downlinkAction[VlanVid] = dlClVid & 0xfff
712 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530713 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800714 "reason": "failed to convert VLANID classifier",
715 "vlan-id": VlanVid}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530716 }
717
David K. Bainbridge794735f2020-02-11 21:01:37 -0800718 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700719 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530720}
721
npujarec5762e2020-01-01 14:08:48 +0530722func (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 +0530723 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800724 allocID uint32, gemPortID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530725 /* One of the OLT platform (Broadcom BAL) requires that symmetric
726 flows require the same flow_id to be used across UL and DL.
727 Since HSIA flow is the only symmetric flow currently, we need to
728 re-use the flow_id across both direction. The 'flow_category'
729 takes priority over flow_cookie to find any available HSIA_FLOW
730 id for the ONU.
731 */
Girish Kumar2ad402b2020-03-20 19:45:12 +0000732 logger.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700733 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530734 "logicalFlow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530735 var vlanPbit uint32 = 0xff // means no pbit
Gamze Abaka724d0852020-03-18 12:10:24 +0000736 var vlanVid uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400737 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000738 vlanPbit = classifier[VlanPcp].(uint32)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000739 logger.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800740 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000741 logger.Debugw("pbit-not-found-in-flow", log.Fields{"vlan-pcp": VlanPcp})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400742 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000743 if _, ok := classifier[VlanVid]; ok {
744 vlanVid = classifier[VlanVid].(uint32)
745 log.Debugw("Found vlan in the flow", log.Fields{"VlanVid": vlanVid})
746 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700747 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530748 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000749 logger.Debug("flow-already-exists")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800750 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530751 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000752 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530753 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530754 return olterrors.NewErrNotFound("hsia-flow-id", log.Fields{"direction": direction}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530755 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800756 classifierProto, err := makeOpenOltClassifierField(classifier)
757 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530758 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530759 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000760 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +0000761 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800762 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530763 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530764 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000765 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800766 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530767 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530768 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800769 log.Fields{
770 "classifier": classifier,
771 "action": action,
772 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530773 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700774 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
775 OnuId: int32(onuID),
776 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000777 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530778 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700779 AllocId: int32(allocID),
780 NetworkIntfId: int32(networkIntfID),
781 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530782 Classifier: classifierProto,
783 Action: actionProto,
784 Priority: int32(logicalFlow.Priority),
785 Cookie: logicalFlow.Cookie,
786 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800787 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530788 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530789 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000790 logger.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800791 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
792 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
793 flow.OnuId,
794 flow.UniId,
795 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530796 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": flow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800797 }
798 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +0530799}
Esin Karamanae41e2b2019-12-17 18:13:13 +0000800
David K. Bainbridge794735f2020-02-11 21:01:37 -0800801func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530802
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530803 networkIntfID, err := getNniIntfID(classifier, action)
804 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530805 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800806 "classifier": classifier,
807 "action": action},
808 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530809 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530810
811 // Clear the action map
812 for k := range action {
813 delete(action, k)
814 }
815
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700816 action[TrapToHost] = true
817 classifier[UDPSrc] = uint32(68)
818 classifier[UDPDst] = uint32(67)
819 classifier[PacketTagType] = SingleTag
820 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530821
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700822 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530823 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000824 logger.Debug("Flow-exists--not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800825 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530826 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530827
David K. Bainbridge794735f2020-02-11 21:01:37 -0800828 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 +0530829
830 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530831 return olterrors.NewErrNotFound("flow", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800832 "interface-id": intfID,
833 "gem-port": gemPortID,
834 "cookie": flowStoreCookie},
835 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530836 }
837
Girish Kumar2ad402b2020-03-20 19:45:12 +0000838 logger.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530839
David K. Bainbridge794735f2020-02-11 21:01:37 -0800840 classifierProto, err := makeOpenOltClassifierField(classifier)
841 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530842 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530843 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000844 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +0000845 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800846 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530847 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530848 }
849
David K. Bainbridge794735f2020-02-11 21:01:37 -0800850 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700851 OnuId: int32(onuID),
852 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530853 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700854 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700855 AllocId: int32(allocID),
856 NetworkIntfId: int32(networkIntfID),
857 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530858 Classifier: classifierProto,
859 Action: actionProto,
860 Priority: int32(logicalFlow.Priority),
861 Cookie: logicalFlow.Cookie,
862 PortNo: portNo}
863
David K. Bainbridge794735f2020-02-11 21:01:37 -0800864 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530865 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800866 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000867 logger.Debug("DHCP UL flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800868 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
869 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
870 dhcpFlow.OnuId,
871 dhcpFlow.UniId,
872 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530873 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId, log.Fields{"flow": dhcpFlow}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530874 }
875
David K. Bainbridge794735f2020-02-11 21:01:37 -0800876 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530877}
878
Esin Karamanae41e2b2019-12-17 18:13:13 +0000879//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +0530880func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
David K. Bainbridge794735f2020-02-11 21:01:37 -0800881 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32) error {
882 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow)
Esin Karamanae41e2b2019-12-17 18:13:13 +0000883}
884
885//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +0530886func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
David K. Bainbridge794735f2020-02-11 21:01:37 -0800887 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +0000888
889 networkIntfID, err := getNniIntfID(classifier, action)
890 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530891 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800892 "classifier": classifier,
893 "action": action},
894 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000895 }
896
897 // Clear the action map
898 for k := range action {
899 delete(action, k)
900 }
901
902 action[TrapToHost] = true
903 classifier[PacketTagType] = SingleTag
904 delete(classifier, VlanVid)
905
906 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530907 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000908 logger.Debug("Flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800909 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +0000910 }
911
npujarec5762e2020-01-01 14:08:48 +0530912 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 +0000913
914 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530915 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800916 "interface-id": intfID,
917 "oni-id": onuID,
918 "cookie": flowStoreCookie,
919 "flow-type": flowType},
920 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000921 }
922
Girish Kumar2ad402b2020-03-20 19:45:12 +0000923 logger.Debugw("Creating upstream trap flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID, "flowType": flowType})
Esin Karamanae41e2b2019-12-17 18:13:13 +0000924
David K. Bainbridge794735f2020-02-11 21:01:37 -0800925 classifierProto, err := makeOpenOltClassifierField(classifier)
926 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530927 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000928 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000929 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +0000930 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800931 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530932 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000933 }
934
David K. Bainbridge794735f2020-02-11 21:01:37 -0800935 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +0000936 OnuId: int32(onuID),
937 UniId: int32(uniID),
938 FlowId: flowID,
939 FlowType: Upstream,
940 AllocId: int32(allocID),
941 NetworkIntfId: int32(networkIntfID),
942 GemportId: int32(gemPortID),
943 Classifier: classifierProto,
944 Action: actionProto,
945 Priority: int32(logicalFlow.Priority),
946 Cookie: logicalFlow.Cookie,
947 PortNo: portNo}
948
David K. Bainbridge794735f2020-02-11 21:01:37 -0800949 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530950 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": flow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800951 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000952 logger.Debugf("%s UL flow added to device successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +0000953
David K. Bainbridge794735f2020-02-11 21:01:37 -0800954 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
955 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
956 flow.OnuId,
957 flow.UniId,
958 flow.FlowId, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530959 return olterrors.NewErrPersistence("update", "flow", flow.FlowId, log.Fields{"flow": flow}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000960 }
961
David K. Bainbridge794735f2020-02-11 21:01:37 -0800962 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +0000963}
964
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700965// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Girish Gowdrafae935c2020-02-17 19:21:44 +0530966func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000967 logger.Debugw("Adding EAPOL to device", log.Fields{"intfId": intfID, "onuId": onuID, "portNo": portNo, "allocId": allocID, "gemPortId": gemPortID, "vlanId": vlanID, "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +0530968
969 uplinkClassifier := make(map[string]interface{})
970 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +0530971
manikkaraj kbf256be2019-03-25 00:13:48 +0530972 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700973 uplinkClassifier[EthType] = uint32(EapEthType)
974 uplinkClassifier[PacketTagType] = SingleTag
975 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +0000976 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +0530977 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700978 uplinkAction[TrapToHost] = true
979 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530980 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000981 logger.Debug("Flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800982 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530983 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530984 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +0000985 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530986 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530987 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800988 "interface-id": intfID,
989 "onu-id": onuID,
990 "coookie": flowStoreCookie},
991 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +0530992 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000993 logger.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530994
David K. Bainbridge794735f2020-02-11 21:01:37 -0800995 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
996 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530997 return olterrors.NewErrInvalidValue(log.Fields{"classifier": uplinkClassifier}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +0530998 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000999 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001000 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001001 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301002 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301003 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001004 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001005 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301006 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301007 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001008 "classifier": classifier,
1009 "action": action},
1010 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301011 }
1012
David K. Bainbridge794735f2020-02-11 21:01:37 -08001013 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001014 OnuId: int32(onuID),
1015 UniId: int32(uniID),
1016 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001017 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001018 AllocId: int32(allocID),
1019 NetworkIntfId: int32(networkIntfID),
1020 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301021 Classifier: classifierProto,
1022 Action: actionProto,
1023 Priority: int32(logicalFlow.Priority),
1024 Cookie: logicalFlow.Cookie,
1025 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001026 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301027 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001028 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001029 logger.Debug("EAPOL UL flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001030 flowCategory := "EAPOL"
1031 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1032 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1033 upstreamFlow.OnuId,
1034 upstreamFlow.UniId,
1035 upstreamFlow.FlowId,
1036 /* lowCategory, */
1037 flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301038 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId, log.Fields{"flow": upstreamFlow}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301039 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301040
Girish Kumar2ad402b2020-03-20 19:45:12 +00001041 logger.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001042 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301043}
1044
David K. Bainbridge794735f2020-02-11 21:01:37 -08001045func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001046 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001047
1048 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1049 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1050 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001051 if vlanID != ReservedVlan {
1052 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001053 classifier.OVid = vid
1054 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301055 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001056 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1057 vid := uint32(metadata)
1058 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001059 classifier.IVid = vid
1060 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301061 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301062 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001063 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301064 classifier.OPbits = vlanPcp
1065 } else {
1066 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301067 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001068 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1069 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1070 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1071 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001072 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001073 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1074 classifier.PktTagType = pktTagType
1075
1076 switch pktTagType {
1077 case SingleTag:
1078 case DoubleTag:
1079 case Untagged:
1080 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001081 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301082 }
1083 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001084 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301085}
1086
Gamze Abaka724d0852020-03-18 12:10:24 +00001087func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001088 var actionCmd openoltpb2.ActionCmd
1089 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301090 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001091 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301092 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001093 if _, ok := actionInfo[VlanPcp]; ok {
1094 action.Cmd.RemarkInnerPbits = true
1095 action.IPbits = actionInfo[VlanPcp].(uint32)
1096 if _, ok := actionInfo[VlanVid]; ok {
1097 action.Cmd.TranslateInnerTag = true
1098 action.IVid = actionInfo[VlanVid].(uint32)
1099 }
1100 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001101 } else if _, ok := actionInfo[PushVlan]; ok {
1102 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301103 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001104 if _, ok := actionInfo[VlanPcp]; ok {
1105 action.OPbits = actionInfo[VlanPcp].(uint32)
1106 action.Cmd.RemarkOuterPbits = true
1107 if _, ok := classifierInfo[VlanVid]; ok {
1108 action.IVid = classifierInfo[VlanVid].(uint32)
1109 action.Cmd.TranslateInnerTag = true
1110 }
1111 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001112 } else if _, ok := actionInfo[TrapToHost]; ok {
1113 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301114 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001115 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301116 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001117 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301118}
1119
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001120// getTPpath return the ETCD path for a given UNI port
1121func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uniPath string, TpID uint32) string {
1122 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301123}
1124
Gamze Abakafee36392019-10-03 11:17:24 +00001125// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301126func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1127 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001128 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1129
Gamze Abakafee36392019-10-03 11:17:24 +00001130 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301131 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001132 olterrors.NewErrAdapter("delete-tech-profile-failed", nil, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301133 // return err
1134 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001135 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001136 log.Debugw("tech-profile-deleted", log.Fields{"deviceId": f.deviceHandler.device.Id, "tp": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001137 }
1138 return nil
1139}
1140
1141// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301142func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001143 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001144 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001145 }
npujarec5762e2020-01-01 14:08:48 +05301146 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001147 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001148 }
1149 return nil
1150}
1151
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001152func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301153 if len(classifier) == 0 { // should never happen
Girish Kumar2ad402b2020-03-20 19:45:12 +00001154 logger.Error("Invalid classfier object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301155 return 0
1156 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001157 logger.Debugw("generating flow store cookie", log.Fields{"classifier": classifier, "gemPortID": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301158 var jsonData []byte
1159 var flowString string
1160 var err error
1161 // TODO: Do we need to marshall ??
1162 if jsonData, err = json.Marshal(classifier); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001163 logger.Error("Failed to encode classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301164 return 0
1165 }
1166 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001167 if gemPortID != 0 {
1168 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301169 }
1170 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001171 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301172 hash := big.NewInt(0)
1173 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301174 generatedHash := hash.Uint64()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001175 logger.Debugw("hash generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301176 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301177}
1178
npujarec5762e2020-01-01 14:08:48 +05301179func (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 +05301180 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001181 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001182 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1183 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1184 */
1185 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001186 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001187 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001188 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001189 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001190 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301191 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001192 if existingFlows != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001193 logger.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001194 //for _, f := range *existingFlows {
1195 // flows = append(flows, f)
1196 //}
1197 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001198 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001199 logger.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
manikkaraj kbf256be2019-03-25 00:13:48 +05301200 return &flows
1201}
1202
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001203//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1204// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1205// var intfId uint32
1206// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1207// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1208// */
1209// if flow.AccessIntfId != -1 {
1210// intfId = uint32(flow.AccessIntfId)
1211// } else {
1212// intfId = uint32(flow.NetworkIntfId)
1213// }
1214// // Get existing flows matching flowid for given subscriber from KV store
1215// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1216// if existingFlows != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001217// logger.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001218// for _, f := range *existingFlows {
1219// flows = append(flows, f)
1220// }
1221// }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001222// logger.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001223// return &flows
1224//}
1225
npujarec5762e2020-01-01 14:08:48 +05301226func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(ctx context.Context, intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001227 logger.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
npujarec5762e2020-01-01 14:08:48 +05301228 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001229 logger.Debug("Error while Storing flow into KV store")
manikkaraj k17652a72019-05-06 09:06:36 -04001230 return err
1231 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001232 logger.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301233 return nil
1234}
1235
David K. Bainbridge794735f2020-02-11 21:01:37 -08001236func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001237
1238 var intfID uint32
1239 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1240 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1241 */
1242 if deviceFlow.AccessIntfId != -1 {
1243 intfID = uint32(deviceFlow.AccessIntfId)
1244 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001245 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001246 intfID = uint32(deviceFlow.NetworkIntfId)
1247 }
1248
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001249 logger.Debugw("sending-flow-to-device-via-grpc", log.Fields{
1250 "flow": *deviceFlow,
1251 "deviceId": f.deviceHandler.device.Id,
1252 })
manikkaraj kbf256be2019-03-25 00:13:48 +05301253 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001254
1255 st, _ := status.FromError(err)
1256 if st.Code() == codes.AlreadyExists {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001257 logger.Debug("flow-already-exists", log.Fields{
1258 "err": err,
1259 "deviceFlow": deviceFlow,
1260 "deviceId": f.deviceHandler.device.Id,
1261 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001262 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301263 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001264
1265 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001266 logger.Errorw("failed-to-Add-flow-to-device", log.Fields{
1267 "err": err,
1268 "deviceFlow": deviceFlow,
1269 "deviceId": f.deviceHandler.device.Id,
1270 })
npujarec5762e2020-01-01 14:08:48 +05301271 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001272 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001273 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301274 if deviceFlow.GemportId != -1 {
1275 // No need to register the flow if it is a trap on nni flow.
npujarec5762e2020-01-01 14:08:48 +05301276 f.registerFlow(ctx, logicalFlow, deviceFlow)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301277 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001278 logger.Debugw("flow-added-to-device-successfully", log.Fields{
1279 "flow": *deviceFlow,
1280 "deviceId": f.deviceHandler.device.Id,
1281 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001282 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001283}
1284
David K. Bainbridge794735f2020-02-11 21:01:37 -08001285func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001286 logger.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001287 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1288 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001289 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001290 logger.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
serkant.uluderya245caba2019-09-24 23:15:29 -07001291 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001292 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001293 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001294 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001295
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001296 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001297 logger.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001298 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301299}
1300
1301/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1302 //update core flows_proxy : flows_proxy.update('/', flows)
1303}
1304
1305func generateStoredId(flowId uint32, direction string)uint32{
1306
David K. Bainbridge82efc492019-09-04 09:57:11 -07001307 if direction == Upstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001308 logger.Debug("Upstream flow shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301309 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001310 }else if direction == Downstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001311 logger.Debug("Downstream flow not shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301312 return flowId
1313 }else{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001314 logger.Errorw("Unrecognized direction",log.Fields{"direction": direction})
manikkaraj kbf256be2019-03-25 00:13:48 +05301315 return flowId
1316 }
1317}
1318
1319*/
1320
David K. Bainbridge794735f2020-02-11 21:01:37 -08001321func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001322
1323 classifierInfo := make(map[string]interface{})
1324 actionInfo := make(map[string]interface{})
1325
1326 classifierInfo[EthType] = uint32(LldpEthType)
1327 classifierInfo[PacketTagType] = Untagged
1328 actionInfo[TrapToHost] = true
1329
1330 // LLDP flow is installed to trap LLDP packets on the NNI port.
1331 // We manage flow_id resource pool on per PON port basis.
1332 // Since this situation is tricky, as a hack, we pass the NNI port
1333 // index (network_intf_id) as PON port Index for the flow_id resource
1334 // pool. Also, there is no ONU Id available for trapping LLDP packets
1335 // on NNI port, use onu_id as -1 (invalid)
1336 // ****************** CAVEAT *******************
1337 // This logic works if the NNI Port Id falls within the same valid
1338 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1339 // we need to have a re-look at this.
1340 // *********************************************
1341
1342 var onuID = -1
1343 var uniID = -1
1344 var gemPortID = -1
1345
David K. Bainbridge794735f2020-02-11 21:01:37 -08001346 networkInterfaceID, err := IntfIDFromNniPortNum(portNo)
1347 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301348 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001349 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001350 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301351 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001352 logger.Debug("Flow-exists--not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001353 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001354 }
npujarec5762e2020-01-01 14:08:48 +05301355 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001356
1357 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301358 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001359 "interface-id": networkInterfaceID,
1360 "onu-id": onuID,
1361 "uni-id": uniID,
1362 "gem-port-id": gemPortID,
1363 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00001364 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001365 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001366 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1367 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001368 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001369 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001370 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001371 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001372 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001373 return olterrors.NewErrInvalidValue(log.Fields{"action": actionInfo}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001374 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001375 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
Humera Kouser94d7a842019-08-25 19:04:32 -04001376
1377 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1378 OnuId: int32(onuID), // OnuId not required
1379 UniId: int32(uniID), // UniId not used
1380 FlowId: flowID,
1381 FlowType: Downstream,
1382 NetworkIntfId: int32(networkInterfaceID),
1383 GemportId: int32(gemPortID),
1384 Classifier: classifierProto,
1385 Action: actionProto,
1386 Priority: int32(flow.Priority),
1387 Cookie: flow.Cookie,
1388 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001389 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001390 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001391 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001392 logger.Debug("LLDP trap on NNI flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001393 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1394 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1395 int32(onuID),
1396 int32(uniID),
1397 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001398 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001399 }
1400 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301401}
1402
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001403func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1404 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001405}
1406
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001407//getOnuDevice to fetch onu from cache or core.
1408func (f *OpenOltFlowMgr) getOnuDevice(intfID uint32, onuID uint32) (*OnuDevice, error) {
1409 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1410 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1411 if !ok {
1412 logger.Debugw("couldnt-find-onu-in-cache", log.Fields{"intfID": intfID, "onuID": onuID})
1413 onuDevice, err := f.getChildDevice(intfID, onuID)
1414 if err != nil {
1415 return nil, olterrors.NewErrNotFound("onu-child-device", log.Fields{"onuId": onuID, "intfID": intfID}, err)
1416 }
1417 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1418 //better to ad the device to cache here.
1419 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1420 } else {
1421 logger.Debugw("Found-onu-in-cache", log.Fields{"intfID": intfID, "onuID": onuID})
1422 }
1423
1424 return onuDev.(*OnuDevice), nil
1425}
1426
1427//getChildDevice to fetch onu
1428func (f *OpenOltFlowMgr) getChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001429 logger.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001430 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001431 onuDevice, err := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
1432 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301433 return nil, olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001434 "interface-id": parentPortNo,
1435 "onu-id": onuID},
Girish Kumarf26e4882020-03-05 06:49:10 +00001436 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301437 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001438 logger.Debugw("Successfully received child device from core", log.Fields{"child_device_id": onuDevice.Id, "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301439 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301440}
1441
1442func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001443 logger.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301444 return nil
1445}
1446
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001447func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001448 logger.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301449}
1450
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001451func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001452 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001453 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001454 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001455 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001456}
1457
Girish Gowdra6b130582019-11-20 16:45:20 +05301458func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001459 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301460 if err != nil {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001461 logger.Debugw("couldnt-find-onu-child-device", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1462 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301463 }
1464
1465 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001466 logger.Debugw("sending gem port delete to openonu adapter", log.Fields{"msg": *delGemPortMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301467 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1468 delGemPortMsg,
1469 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
1470 f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001471 onuDev.deviceType,
1472 onuDev.deviceID,
1473 onuDev.proxyDeviceID, ""); sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001474 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001475 "toAdapter": onuDev.deviceType, "onuId": onuDev.deviceID,
1476 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301477 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001478 logger.Debugw("success sending del gem port to onu adapter", log.Fields{"msg": delGemPortMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301479 return nil
1480}
1481
1482func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001483 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301484 if err != nil {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001485 logger.Debugw("couldnt-find-onu-child-device", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1486 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301487 }
1488
1489 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001490 logger.Debugw("sending tcont delete to openonu adapter", log.Fields{"msg": *delTcontMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301491 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1492 delTcontMsg,
1493 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
1494 f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001495 onuDev.deviceType,
1496 onuDev.deviceID,
1497 onuDev.proxyDeviceID, ""); sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001498 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001499 "toAdapter": onuDev.deviceType, "onuId": onuDev.deviceID,
1500 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301501 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001502 logger.Debugw("success sending del tcont to onu adapter", log.Fields{"msg": delTcontMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301503 return nil
1504}
1505
Girish Gowdra3d633032019-12-10 16:37:05 +05301506func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1507 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1508 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1509 if val.(int) > 0 {
1510 pnFlDels := val.(int) - 1
1511 if pnFlDels > 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001512 logger.Debugw("flow delete succeeded, more pending",
Girish Gowdra3d633032019-12-10 16:37:05 +05301513 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1514 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1515 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001516 logger.Debugw("all pending flow deletes handled, removing entry from map",
Girish Gowdra3d633032019-12-10 16:37:05 +05301517 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1518 f.pendingFlowDelete.Delete(pnFlDelKey)
1519 }
1520 }
1521 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001522 logger.Debugw("no pending delete flows found",
Girish Gowdra3d633032019-12-10 16:37:05 +05301523 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1524
1525 }
1526
1527}
1528
Girish Gowdrac3037402020-01-22 20:29:53 +05301529// Once the gemport is released for a given onu, it also has to be cleared from local cache
1530// which was used for deriving the gemport->logicalPortNo during packet-in.
1531// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1532// is conveyed to ONOS during packet-in OF message.
1533func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(intfID uint32, onuID uint32, gemPortID uint32) {
1534 f.lockCache.Lock()
1535 defer f.lockCache.Unlock()
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001536 logger.Debugw("deleting-gem-from-local-cache",
1537 log.Fields{"gem": gemPortID, "intf": intfID, "onu": onuID, "deviceId": f.deviceHandler.device.Id, "onuGem": f.onuGemInfo[intfID]})
Girish Gowdrac3037402020-01-22 20:29:53 +05301538 onugem := f.onuGemInfo[intfID]
serkant.uluderya96af4932020-02-20 16:58:48 -08001539 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301540 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001541 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301542 // If the gemport is found, delete it from local cache.
1543 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001544 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1545 onugem[i] = onu
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001546 logger.Debugw("removed-gemport-from-local-cache",
1547 log.Fields{"intfID": intfID, "onuID": onuID, "deletedGemPortID": gemPortID, "gemPorts": onu.GemPorts, "deviceId": f.deviceHandler.device.Id})
Girish Gowdrac3037402020-01-22 20:29:53 +05301548 break
1549 }
1550 }
1551 break
1552 }
1553 }
1554}
1555
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301556//clearResources clears pon resources in kv store and the device
npujarec5762e2020-01-01 14:08:48 +05301557func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301558 gemPortID int32, flowID uint32, flowDirection string,
1559 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001560
Chaitrashree G S90a17952019-11-14 21:51:21 -05001561 tpID, err := getTpIDFromFlow(flow)
1562 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001563 return olterrors.NewErrNotFound("tpid", log.Fields{"flow": flow, "pon": Intf, "onuID": onuID, "uniID": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001564 }
Gamze Abakafee36392019-10-03 11:17:24 +00001565
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001566 if len(updatedFlows) >= 0 {
1567 // There are still flows referencing the same flow_id.
1568 // So the flow should not be freed yet.
1569 // For ex: Case of HSIA where same flow is shared
1570 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00001571 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
1572 olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": updatedFlows}, err).Log()
1573 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001574 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05301575 // Do this for subscriber flows only (not trap from NNI flows)
1576 if onuID != -1 && uniID != -1 {
1577 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1578 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001579 logger.Debugw("creating entry for pending flow delete",
Girish Gowdra3d633032019-12-10 16:37:05 +05301580 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1581 f.pendingFlowDelete.Store(pnFlDelKey, 1)
1582 } else {
1583 pnFlDels := val.(int) + 1
Girish Kumar2ad402b2020-03-20 19:45:12 +00001584 logger.Debugw("updating flow delete entry",
Girish Gowdra3d633032019-12-10 16:37:05 +05301585 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1586 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1587 }
1588
1589 defer f.deletePendingFlows(Intf, onuID, uniID)
1590 }
1591
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001592 logger.Debugw("releasing-flow-id-to-resource-manager", log.Fields{
1593 "Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID,
1594 "deviceId": f.deviceHandler.device.Id,
1595 })
npujarec5762e2020-01-01 14:08:48 +05301596 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001597
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001598 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301599 tpPath := f.getTPpath(Intf, uni, tpID)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001600 logger.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
npujarec5762e2020-01-01 14:08:48 +05301601 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00001602 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1603 return olterrors.NewErrNotFound("tech-profile-in-kv-store", log.Fields{"tpID": tpID, "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00001604 }
1605
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301606 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001607 if f.isGemPortUsedByAnotherFlow(gemPK) {
1608 flowIDs := f.flowsUsedByGemPort[gemPK]
1609 for i, flowIDinMap := range flowIDs {
1610 if flowIDinMap == flowID {
1611 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301612 // everytime flowsUsedByGemPort cache is updated the same should be updated
1613 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001614 f.flowsUsedByGemPort[gemPK] = flowIDs
npujarec5762e2020-01-01 14:08:48 +05301615 f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00001616 break
1617 }
1618 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001619 logger.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301620 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001621 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001622 logger.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301623 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001624 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1625 // 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 +05301626 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Girish Gowdrac3037402020-01-22 20:29:53 +05301627 f.deleteGemPortFromLocalCache(Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001628 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301629 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1630 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001631 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05301632 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1633 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001634 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05301635 // Delete the gem port on the ONU.
1636 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001637 logger.Errorw("error processing delete gem-port towards onu",
Girish Gowdra6b130582019-11-20 16:45:20 +05301638 log.Fields{"err": err, "pon": Intf, "onuID": onuID, "uniID": uniID, "gemPortId": gemPortID})
1639 }
Gamze Abakafee36392019-10-03 11:17:24 +00001640
npujarec5762e2020-01-01 14:08:48 +05301641 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001642 if !ok {
npujarec5762e2020-01-01 14:08:48 +05301643 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
1644 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1645 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1646 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
1647 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301648 // Delete the TCONT on the ONU.
1649 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001650 logger.Errorw("error processing delete tcont towards onu",
Girish Gowdra6b130582019-11-20 16:45:20 +05301651 log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID, "allocId": techprofileInst.UsScheduler.AllocID})
1652 }
Gamze Abakafee36392019-10-03 11:17:24 +00001653 }
1654 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001655 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301656 return nil
1657}
1658
David K. Bainbridge794735f2020-02-11 21:01:37 -08001659// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301660func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301661
Girish Kumar2ad402b2020-03-20 19:45:12 +00001662 logger.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
Esin Karamanccb714b2019-11-29 15:02:06 +00001663
1664 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05301665 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001666 return
1667 }
1668
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301669 var updatedFlows []rsrcMgr.FlowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301670 classifierInfo := make(map[string]interface{})
1671
1672 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1673 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001674 logger.Error(err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301675 return
1676 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301677
David K. Bainbridge794735f2020-02-11 21:01:37 -08001678 onuID := int32(onu)
1679 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301680
1681 for _, field := range flows.GetOfbFields(flow) {
1682 if field.Type == flows.IP_PROTO {
1683 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001684 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301685 }
1686 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001687 logger.Debugw("Extracted access info from flow to be deleted",
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301688 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1689
1690 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1691 onuID = -1
1692 uniID = -1
Girish Kumar2ad402b2020-03-20 19:45:12 +00001693 logger.Debug("Trap on nni flow set oni, uni to -1")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001694 Intf, err = IntfIDFromNniPortNum(inPort)
1695 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001696 logger.Errorw("invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001697 log.Fields{
1698 "port-number": inPort,
1699 "error": err})
1700 return
1701 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301702 }
npujarec5762e2020-01-01 14:08:48 +05301703 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001704 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05301705 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301706 if flowInfo == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001707 logger.Debugw("No FlowInfo found found in KV store",
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301708 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1709 return
1710 }
1711 updatedFlows = nil
1712 for _, flow := range *flowInfo {
1713 updatedFlows = append(updatedFlows, flow)
1714 }
1715
1716 for i, storedFlow := range updatedFlows {
1717 if flow.Id == storedFlow.LogicalFlowID {
1718 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001719 logger.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001720 // DKB
1721 if err = f.removeFlowFromDevice(&removeFlowMessage); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001722 logger.Errorw("failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001723 return
1724 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001725 logger.Debug("Flow removed from device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001726 //Remove the Flow from FlowInfo
1727 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1728 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1729 flowID, flowDirection, portNum, updatedFlows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001730 logger.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301731 return
1732 }
1733 }
1734 }
1735 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001736}
1737
Esin Karamanccb714b2019-11-29 15:02:06 +00001738//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
1739// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05301740func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00001741 classifierInfo := make(map[string]interface{})
1742 formulateClassifierInfoFromFlow(classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00001743 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00001744
1745 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001746 logger.Warnw("No inPort found. Cannot release resources of the multicast flow.", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001747 return
1748 }
1749
Esin Karamanccb714b2019-11-29 15:02:06 +00001750 var onuID = int32(NoneOnuID)
1751 var uniID = int32(NoneUniID)
1752 var flowID uint32
1753 var updatedFlows []rsrcMgr.FlowInfo
1754
npujarec5762e2020-01-01 14:08:48 +05301755 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001756
1757 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05301758 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001759 if flowInfo == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001760 logger.Debugw("No multicast FlowInfo found in the KV store",
Esin Karamanccb714b2019-11-29 15:02:06 +00001761 log.Fields{"Intf": networkInterfaceID, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1762 continue
1763 }
1764 updatedFlows = nil
1765 for _, flow := range *flowInfo {
1766 updatedFlows = append(updatedFlows, flow)
1767 }
1768 for i, storedFlow := range updatedFlows {
1769 if flow.Id == storedFlow.LogicalFlowID {
1770 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001771 logger.Debugw("Multicast flow to be deleted", log.Fields{"flow": storedFlow})
Esin Karamanccb714b2019-11-29 15:02:06 +00001772 //remove from device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001773 if err := f.removeFlowFromDevice(&removeFlowMessage); err != nil {
1774 // DKB
Girish Kumar2ad402b2020-03-20 19:45:12 +00001775 logger.Errorw("failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001776 log.Fields{
1777 "flow-id": flow.Id,
1778 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001779 return
1780 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001781 logger.Debugw("Multicast flow removed from device successfully", log.Fields{"flowId": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001782 //Remove the Flow from FlowInfo
1783 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05301784 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001785 logger.Error("Failed to delete multicast flow from the KV store", log.Fields{"flow": storedFlow, "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001786 return
1787 }
1788 //release flow id
Girish Kumar2ad402b2020-03-20 19:45:12 +00001789 logger.Debugw("Releasing multicast flow id", log.Fields{"flowId": flowID, "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05301790 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001791 }
1792 }
1793 }
1794}
1795
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001796//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07001797func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001798 logger.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301799 var direction string
1800 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001801
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301802 for _, action := range flows.GetActions(flow) {
1803 if action.Type == flows.OUTPUT {
1804 if out := action.GetOutput(); out != nil {
1805 actionInfo[Output] = out.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001806 logger.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301807 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001808 logger.Error("Invalid output port in action")
Girish Gowdracefae192020-03-19 18:14:10 -07001809 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001810 }
1811 }
1812 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001813
1814 if flows.HasGroup(flow) {
1815 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07001816 f.clearFlowFromResourceManager(ctx, flow, direction)
1817 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00001818 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301819 direction = Upstream
1820 } else {
1821 direction = Downstream
1822 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301823
Girish Gowdracefae192020-03-19 18:14:10 -07001824 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(flow, direction)
1825 if err != nil {
1826 return err
1827 }
1828
1829 userKey := tpLockKey{intfID, onuID, uniID}
1830
1831 // Serialize flow removes on a per subscriber basis
1832 if f.perUserFlowHandleLock.TryLock(userKey) {
1833 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
1834 f.perUserFlowHandleLock.Unlock(userKey)
1835 } else {
1836 // Ideally this should never happen
Girish Kumar2ad402b2020-03-20 19:45:12 +00001837 logger.Errorw("failed to acquire lock to remove flow, flow remove aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001838 return errors.New("failed-to-acquire-per-user-lock")
1839 }
1840
1841 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001842}
1843
Girish Gowdra3d633032019-12-10 16:37:05 +05301844func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
1845 uniID uint32, ch chan bool) {
1846 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1847 for {
1848 select {
1849 case <-time.After(20 * time.Millisecond):
1850 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001851 logger.Debug("pending flow deletes completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05301852 ch <- true
1853 return
1854 }
1855 case <-ctx.Done():
Girish Kumar2ad402b2020-03-20 19:45:12 +00001856 logger.Error("flow delete wait handler routine canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05301857 return
1858 }
1859 }
1860}
1861
Esin Karamanae41e2b2019-12-17 18:13:13 +00001862//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
1863func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
1864 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
1865 if ethType, ok := classifierInfo[EthType]; ok {
1866 if ethType.(uint32) == IPv4EthType {
1867 if ipProto, ok := classifierInfo[IPProto]; ok {
1868 if ipProto.(uint32) == IgmpProto {
1869 return true
1870 }
1871 }
1872 }
1873 }
1874 }
1875 return false
1876}
1877
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001878// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301879// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01001880func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001881 classifierInfo := make(map[string]interface{})
1882 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001883 var UsMeterID uint32
1884 var DsMeterID uint32
1885
Girish Kumar2ad402b2020-03-20 19:45:12 +00001886 logger.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001887 formulateClassifierInfoFromFlow(classifierInfo, flow)
1888
1889 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1890 if err != nil {
1891 // Error logging is already done in the called function
1892 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001893 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301894 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001895
Esin Karamanccb714b2019-11-29 15:02:06 +00001896 if flows.HasGroup(flow) {
1897 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01001898 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001899 }
1900
manikkaraj k17652a72019-05-06 09:06:36 -04001901 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001902 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1903 if err != nil {
1904 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01001905 return err
manikkaraj k17652a72019-05-06 09:06:36 -04001906 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001907
Girish Kumar2ad402b2020-03-20 19:45:12 +00001908 logger.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001909 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001910
Humera Kouser94d7a842019-08-25 19:04:32 -04001911 if ethType, ok := classifierInfo[EthType]; ok {
1912 if ethType.(uint32) == LldpEthType {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001913 logger.Info("Adding LLDP flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01001914 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04001915 }
1916 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001917 if ipProto, ok := classifierInfo[IPProto]; ok {
1918 if ipProto.(uint32) == IPProtoDhcp {
1919 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301920 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001921 logger.Debug("trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01001922 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001923 }
1924 }
1925 }
1926 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001927 if isIgmpTrapDownstreamFlow(classifierInfo) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001928 logger.Debug("trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01001929 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001930 }
A R Karthick1f85b802019-10-11 05:06:05 +00001931
1932 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
npujarec5762e2020-01-01 14:08:48 +05301933 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001934
Chaitrashree G S90a17952019-11-14 21:51:21 -05001935 TpID, err := getTpIDFromFlow(flow)
1936 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001937 return olterrors.NewErrNotFound("tpid-for-flow", log.Fields{"flow": flow, "pon": IntfID, "onuID": onuID, "uniID": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001938 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001939 logger.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001940 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001941 UsMeterID = flows.GetMeterIdFromFlow(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001942 logger.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001943 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001944 DsMeterID = flows.GetMeterIdFromFlow(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001945 logger.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001946
1947 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301948
1949 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1950 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001951 logger.Debugw("no pending flows found, going ahead with flow install", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
npujarec5762e2020-01-01 14:08:48 +05301952 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05301953 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05301954 pendingFlowDelComplete := make(chan bool)
1955 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
1956 select {
1957 case <-pendingFlowDelComplete:
Girish Kumar2ad402b2020-03-20 19:45:12 +00001958 logger.Debugw("all pending flow deletes completed", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
npujarec5762e2020-01-01 14:08:48 +05301959 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05301960
1961 case <-time.After(10 * time.Second):
Girish Kumarf26e4882020-03-05 06:49:10 +00001962 return olterrors.NewErrTimeout("pending-flow-deletes", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID}, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +05301963 }
1964 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001965 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001966}
1967
Esin Karamanccb714b2019-11-29 15:02:06 +00001968// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08001969func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00001970 classifierInfo[PacketTagType] = DoubleTag
Girish Kumar2ad402b2020-03-20 19:45:12 +00001971 logger.Debugw("add-multicast-flow", log.Fields{"classifierInfo": classifierInfo, "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00001972
Esin Karaman65409d82020-03-18 10:58:18 +00001973 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00001974 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001975 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00001976 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00001977 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
1978 //otherwise, classification is based on ipv4_dst by default.
1979 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
1980 mcastFlowClassificationByEthDst := false
1981
1982 if mcastFlowClassificationByEthDst {
1983 //replace ipDst with ethDst
1984 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
1985 flows.IsMulticastIp(ipv4Dst.(uint32)) {
1986 // replace ipv4_dst classifier with eth_dst
1987 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
1988 delete(classifierInfo, Ipv4Dst)
1989 classifierInfo[EthDst] = multicastMac
Girish Kumar2ad402b2020-03-20 19:45:12 +00001990 logger.Debugw("multicast-ip-to-mac-conversion-success", log.Fields{"ip:": ipv4Dst.(uint32), "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00001991 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001992 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00001993 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00001994
David K. Bainbridge794735f2020-02-11 21:01:37 -08001995 onuID := NoneOnuID
1996 uniID := NoneUniID
1997 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00001998
David K. Bainbridge794735f2020-02-11 21:01:37 -08001999 flowStoreCookie := getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302000 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002001 logger.Debugw("multicast-flow-exists-not-re-adding", log.Fields{"classifierInfo": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002002 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002003 }
npujarec5762e2020-01-01 14:08:48 +05302004 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00002005 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302006 return olterrors.NewErrNotFound("multicast-flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002007 "interface-id": networkInterfaceID,
2008 "onu-id": onuID,
2009 "uni-id": uniID,
2010 "gem-port-id": gemPortID,
2011 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002012 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002013 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002014 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2015 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002016 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002017 }
2018 groupID := actionInfo[GroupID].(uint32)
2019 multicastFlow := openoltpb2.Flow{
2020 FlowId: flowID,
2021 FlowType: Multicast,
2022 NetworkIntfId: int32(networkInterfaceID),
2023 GroupId: groupID,
2024 Classifier: classifierProto,
2025 Priority: int32(flow.Priority),
2026 Cookie: flow.Cookie}
2027
David K. Bainbridge794735f2020-02-11 21:01:37 -08002028 if err = f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002029 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002030 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002031 logger.Debug("multicast flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002032 //get cached group
2033 group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true)
2034 if err == nil {
2035 //calling groupAdd to set group members after multicast flow creation
Andrea Campanellac63bba92020-03-10 17:01:04 +01002036 if err = f.ModifyGroup(ctx, group); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002037 //cached group can be removed now
2038 f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002039 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002040 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002041 }
2042 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002043
2044 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2045 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2046 int32(onuID),
2047 int32(uniID),
2048 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002049 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002050 }
2051 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002052}
2053
Esin Karaman65409d82020-03-18 10:58:18 +00002054//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2055func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2056 if inPort, ok := classifierInfo[InPort]; ok {
2057 nniInterfaceID, err := IntfIDFromNniPortNum(inPort.(uint32))
2058 if err != nil {
2059 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2060 }
2061 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002062 }
Esin Karaman65409d82020-03-18 10:58:18 +00002063 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302064 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002065 if e == nil && len(nniPorts) > 0 {
2066 return nniPorts[0], nil
2067 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302068 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002069}
2070
2071// AddGroup add or update the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002072func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002073 logger.Infow("add-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002074 if group == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002075 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002076 }
2077
2078 groupToOlt := openoltpb2.Group{
2079 GroupId: group.Desc.GroupId,
2080 Command: openoltpb2.Group_SET_MEMBERS,
2081 Action: f.buildGroupAction(),
2082 }
2083
Girish Kumar2ad402b2020-03-20 19:45:12 +00002084 logger.Debugw("Sending group to device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05302085 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002086 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002087 return olterrors.NewErrAdapter("add-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002088 }
2089 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05302090 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002091 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002092 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002093 logger.Debugw("add-group operation performed on the device successfully ", log.Fields{"groupToOlt": groupToOlt})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002094 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002095}
2096
2097//buildGroupAction creates and returns a group action
2098func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2099 var actionCmd openoltpb2.ActionCmd
2100 var action openoltpb2.Action
2101 action.Cmd = &actionCmd
2102 //pop outer vlan
2103 action.Cmd.RemoveOuterTag = true
2104 return &action
2105}
2106
2107// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002108func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002109 logger.Infow("modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002110 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002111 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002112 }
2113
Andrea Campanellac63bba92020-03-10 17:01:04 +01002114 newGroup := f.buildGroup(group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002115 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302116 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002117
2118 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002119 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002120 }
2121
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002122 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002123 if groupExists {
2124 // group already exists
2125 current = f.buildGroup(group.Desc.GroupId, val.Desc.GetBuckets())
Girish Kumar2ad402b2020-03-20 19:45:12 +00002126 logger.Debugw("modify-group: group exists.", log.Fields{"group on the device": val, "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002127 } else {
2128 current = f.buildGroup(group.Desc.GroupId, nil)
2129 }
2130
Girish Kumar2ad402b2020-03-20 19:45:12 +00002131 logger.Debugw("modify-group: comparing current and new.", log.Fields{"group on the device": current, "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002132 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002133 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002134 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002135 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002136
Girish Kumar2ad402b2020-03-20 19:45:12 +00002137 logger.Infow("modify-group -> differences found", log.Fields{"membersToBeAdded": membersToBeAdded,
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002138 "membersToBeRemoved": membersToBeRemoved, "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002139
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002140 groupToOlt := openoltpb2.Group{
2141 GroupId: group.Desc.GroupId,
2142 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002143 var errAdd, errRemoved error
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002144 if membersToBeAdded != nil && len(membersToBeAdded) > 0 {
2145 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2146 groupToOlt.Members = membersToBeAdded
2147 //execute addMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002148 errAdd = f.callGroupAddRemove(&groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002149 }
2150 if membersToBeRemoved != nil && len(membersToBeRemoved) > 0 {
2151 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2152 groupToOlt.Members = membersToBeRemoved
2153 //execute removeMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002154 errRemoved = f.callGroupAddRemove(&groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002155 }
2156
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002157 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002158 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302159 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002160 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002161 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002162 logger.Debugw("modify-group was success. Storing the group", log.Fields{"group": group, "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002163 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002164 logger.Warnw("One of the group add/remove operations has failed. Cannot save group modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002165 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002166 if errAdd != nil {
2167 return errAdd
2168 }
2169 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002170 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002171 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002172}
2173
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002174//callGroupAddRemove performs add/remove buckets operation for the indicated group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002175func (f *OpenOltFlowMgr) callGroupAddRemove(group *openoltpb2.Group) error {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002176 if err := f.performGroupOperation(group); err != nil {
2177 st, _ := status.FromError(err)
2178 //ignore already exists error code
2179 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002180 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002181 }
2182 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002183 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002184}
2185
2186//findDiff compares group members and finds members which only exists in groups2
2187func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2188 var members []*openoltpb2.GroupMember
2189 for _, bucket := range group2.Members {
2190 if !f.contains(group1.Members, bucket) {
2191 // bucket does not exist and must be added
2192 members = append(members, bucket)
2193 }
2194 }
2195 return members
2196}
2197
2198//contains returns true if the members list contains the given member; false otherwise
2199func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2200 for _, groupMember := range members {
2201 if groupMember.InterfaceId == member.InterfaceId {
2202 return true
2203 }
2204 }
2205 return false
2206}
2207
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002208//performGroupOperation call performGroupOperation operation of openolt proto
2209func (f *OpenOltFlowMgr) performGroupOperation(group *openoltpb2.Group) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002210 logger.Debugw("Sending group to device", log.Fields{"groupToOlt": group, "command": group.Command})
Esin Karamanccb714b2019-11-29 15:02:06 +00002211 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2212 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002213 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002214 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002215 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002216}
2217
2218//buildGroup build openoltpb2.Group from given group id and bucket list
2219func (f *OpenOltFlowMgr) buildGroup(groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
2220 group := openoltpb2.Group{
2221 GroupId: groupID}
2222 // create members of the group
2223 if buckets != nil {
2224 for _, ofBucket := range buckets {
2225 member := f.buildMember(ofBucket)
2226 if member != nil && !f.contains(group.Members, member) {
2227 group.Members = append(group.Members, member)
2228 }
2229 }
2230 }
2231 return &group
2232}
2233
2234//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
2235func (f *OpenOltFlowMgr) buildMember(ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
2236 var outPort uint32
2237 outPortFound := false
2238 for _, ofAction := range ofBucket.Actions {
2239 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2240 outPort = ofAction.GetOutput().Port
2241 outPortFound = true
2242 }
2243 }
2244
2245 if !outPortFound {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002246 logger.Debugw("bucket skipped since no out port found in it",
Esin Karamanccb714b2019-11-29 15:02:06 +00002247 log.Fields{"ofBucket": ofBucket})
2248 return nil
2249 }
2250 interfaceID := IntfIDFromUniPortNum(outPort)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002251 logger.Debugw("got associated interface id of the port", log.Fields{"portNumber:": outPort, "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002252 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2253 member := openoltpb2.GroupMember{
2254 InterfaceId: interfaceID,
2255 InterfaceType: openoltpb2.GroupMember_PON,
2256 GemPortId: groupInfo.gemPortID,
2257 Priority: groupInfo.servicePriority,
2258 }
2259 //add member to the group
2260 return &member
2261 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002262 logger.Warnf("bucket skipped since interface-2-gem mapping cannot be found",
Esin Karamanccb714b2019-11-29 15:02:06 +00002263 log.Fields{"ofBucket": ofBucket})
2264 return nil
2265}
2266
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002267//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04002268func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002269
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002270 onuDev, err := f.getOnuDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302271 if err != nil {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002272 logger.Errorw("couldnt-find-onu-child-device", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
2273 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302274 }
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002275 logger.Debugw("Got child device from OLT device handler", log.Fields{"deviceId": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002276
Manikkaraj kb1d51442019-07-23 10:41:02 -04002277 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002278 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002279 logger.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
manikkaraj k17652a72019-05-06 09:06:36 -04002280 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2281 tpDownloadMsg,
2282 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
2283 f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002284 onuDev.deviceType,
2285 onuDev.deviceID,
2286 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002287 if sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002288 return olterrors.NewErrCommunication("send-techprofile-download-request", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002289 "toAdapter": onuDev.deviceType, "onuId": onuDev.deviceID,
2290 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002291 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002292 logger.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302293 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302294}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002295
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302296//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002297func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302298
2299 f.lockCache.Lock()
2300 defer f.lockCache.Unlock()
2301 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2302 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002303 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002304 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302305 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002306 logger.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "onu": onu, "deviceId": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002307 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002308}
2309
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302310//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302311func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302312 f.lockCache.Lock()
2313 defer f.lockCache.Unlock()
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002314 logger.Debugw("adding-gem-to-onu-info-map",
2315 log.Fields{"gem": gemPort, "intf": intfID, "onu": onuID, "deviceId": f.deviceHandler.device.Id, "onuGem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302316 onugem := f.onuGemInfo[intfID]
2317 // update the gem to the local cache as well as to kv strore
2318 for idx, onu := range onugem {
2319 if onu.OnuID == onuID {
2320 // check if gem already exists , else update the cache and kvstore
2321 for _, gem := range onu.GemPorts {
2322 if gem == gemPort {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002323 logger.Debugw("gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2324 log.Fields{"gem": gemPort, "deviceId": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302325 return
2326 }
2327 }
2328 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2329 f.onuGemInfo[intfID] = onugem
2330 }
2331 }
npujarec5762e2020-01-01 14:08:48 +05302332 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302333 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002334 logger.Errorw("failed-to-add-gem-to-onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort, "deviceId": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002335 return
2336 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002337 logger.Debugw("gem-added-to-onu-info-map",
2338 log.Fields{"gem": gemPort, "intf": intfID, "onu": onuID, "deviceId": f.deviceHandler.device.Id, "onuGem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002339}
2340
2341// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002342
2343//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
2344func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302345
2346 f.lockCache.Lock()
2347 defer f.lockCache.Unlock()
2348
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002349 logger.Debugw("Getting-ONU-ID-from-GEM-port-and-PON-port", log.Fields{
2350 "deviceId": f.deviceHandler.device.Id, "onuGemInfo": f.onuGemInfo[intfID],
2351 "serialNumber": serialNumber, "intfId": intfID, "gemPortId": gemPortID})
2352
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302353 // get onuid from the onugem info cache
2354 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002355
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302356 for _, onu := range onugem {
2357 for _, gem := range onu.GemPorts {
2358 if gem == gemPortID {
2359 return onu.OnuID, nil
2360 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002361 }
2362 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302363 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002364 "serial-number": serialNumber,
2365 "interface-id": intfID,
2366 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00002367 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002368}
2369
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002370//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302371func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002372 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002373 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002374 var err error
2375
2376 if packetIn.IntfType == "pon" {
2377 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002378 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002379 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002380 return logicalPortNum, err
2381 }
2382 if packetIn.PortNo != 0 {
2383 logicalPortNum = packetIn.PortNo
2384 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002385 uniID := uint32(0) // FIXME - multi-uni support
2386 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002387 }
2388 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
npujarec5762e2020-01-01 14:08:48 +05302389 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002390 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002391 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002392 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002393 logger.Debugw("Retrieved logicalport from packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08002394 "logicalPortNum": logicalPortNum,
2395 "IntfType": packetIn.IntfType,
2396 "packet": hex.EncodeToString(packetIn.Pkt),
2397 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002398 return logicalPortNum, nil
2399}
2400
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002401//GetPacketOutGemPortID returns gemPortId
npujarec5762e2020-01-01 14:08:48 +05302402func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002403 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002404 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302405
2406 f.lockCache.Lock()
2407 defer f.lockCache.Unlock()
2408 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
2409
2410 gemPortID, ok := f.packetInGemPort[pktInkey]
2411 if ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002412 logger.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302413 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002414 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302415 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
npujarec5762e2020-01-01 14:08:48 +05302416 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302417 if err == nil {
2418 if gemPortID != 0 {
2419 f.packetInGemPort[pktInkey] = gemPortID
Girish Kumar2ad402b2020-03-20 19:45:12 +00002420 logger.Debugw("Found gem port from kv store and updating cache with gemport",
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302421 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
2422 return gemPortID, nil
2423 }
2424 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002425 return uint32(0), olterrors.NewErrNotFound("gem-port", log.Fields{"pktinkey": pktInkey, "gem": gemPortID}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002426}
2427
npujarec5762e2020-01-01 14:08:48 +05302428func installFlowOnAllGemports(ctx context.Context,
2429 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04002430 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
David K. Bainbridge794735f2020-02-11 21:01:37 -08002431 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32) error,
npujarec5762e2020-01-01 14:08:48 +05302432 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05302433 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302434 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05302435 ) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04002436 args map[string]uint32,
2437 classifier map[string]interface{}, action map[string]interface{},
2438 logicalFlow *ofp.OfpFlowStats,
2439 gemPorts []uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05302440 TpInst *tp.TechProfile,
Manikkaraj kb1d51442019-07-23 10:41:02 -04002441 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00002442 direction string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00002443 vlanID ...uint32) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002444 logger.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05302445
Gamze Abaka724d0852020-03-18 12:10:24 +00002446 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
2447 // We need to trim prefix "0b", before further processing
2448 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
2449 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
2450
2451 // If a particular character in the string is set to '1', identify the index of this character from
2452 // the LSB position which marks the PCP bit consumed by the given gem port.
2453 // This PCP bit now becomes a classifier in the flow.
2454
2455 attributes := TpInst.DownstreamGemPortAttributeList
2456 if direction == Upstream {
2457 attributes = TpInst.UpstreamGemPortAttributeList
2458 }
2459
2460 for _, gemPortAttribute := range attributes {
2461 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
2462 continue
2463 }
2464 gemPortID := gemPortAttribute.GemportID
2465 if allPbitsMarked(gemPortAttribute.PbitMap) {
2466 classifier[VlanPcp] = uint32(VlanPCPMask)
2467 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
2468 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
2469 } else if FlowType == EapolFlow {
2470 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0])
2471 }
2472 } else {
2473 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
2474 if pbitSet == BinaryBit1 {
2475 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
2476 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
2477 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
2478 } else if FlowType == EapolFlow {
2479 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0])
2480 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05302481 }
2482 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002483 }
2484 }
2485}
2486
Gamze Abaka724d0852020-03-18 12:10:24 +00002487func allPbitsMarked(pbitMap string) bool {
2488 for pos, pBit := range pbitMap {
2489 if pos >= 2 && pBit != BinaryBit1 {
2490 return false
2491 }
2492 }
2493 return true
2494}
2495
David K. Bainbridge794735f2020-02-11 21:01:37 -08002496func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002497 logger.Debug("Adding trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002498 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002499 classifier[PacketTagType] = DoubleTag
2500 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002501 /* We manage flowId resource pool on per PON port basis.
2502 Since this situation is tricky, as a hack, we pass the NNI port
2503 index (network_intf_id) as PON port Index for the flowId resource
2504 pool. Also, there is no ONU Id available for trapping DHCP packets
2505 on NNI port, use onu_id as -1 (invalid)
2506 ****************** CAVEAT *******************
2507 This logic works if the NNI Port Id falls within the same valid
2508 range of PON Port Ids. If this doesn't work for some OLT Vendor
2509 we need to have a re-look at this.
2510 *********************************************
2511 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002512 onuID := -1
2513 uniID := -1
2514 gemPortID := -1
2515 allocID := -1
David K. Bainbridge794735f2020-02-11 21:01:37 -08002516 networkInterfaceID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302517 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302518 return olterrors.NewErrNotFound("nni-intreface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002519 "classifier": classifier,
2520 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002521 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302522 }
2523
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002524 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302525 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002526 logger.Debug("Flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002527 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002528 }
Gamze Abaka724d0852020-03-18 12:10:24 +00002529 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002530 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302531 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002532 "interface-id": networkInterfaceID,
2533 "onu-id": onuID,
2534 "uni-id": uniID,
2535 "gem-port-id": gemPortID,
2536 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002537 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002538 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002539 classifierProto, err := makeOpenOltClassifierField(classifier)
2540 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002541 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002542 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002543 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002544 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002545 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002546 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002547 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002548 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002549 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2550 OnuId: int32(onuID), // OnuId not required
2551 UniId: int32(uniID), // UniId not used
2552 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002553 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002554 AllocId: int32(allocID), // AllocId not used
2555 NetworkIntfId: int32(networkInterfaceID),
2556 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002557 Classifier: classifierProto,
2558 Action: actionProto,
2559 Priority: int32(logicalFlow.Priority),
2560 Cookie: logicalFlow.Cookie,
2561 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002562 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002563 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002564 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002565 logger.Debug("DHCP trap on NNI flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002566 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
2567 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2568 int32(onuID),
2569 int32(uniID),
2570 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002571 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002572 }
2573 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002574}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002575
Esin Karamanae41e2b2019-12-17 18:13:13 +00002576//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2577func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2578 var packetType string
2579 ovid, ivid := false, false
2580 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2581 vid := vlanID & VlanvIDMask
2582 if vid != ReservedVlan {
2583 ovid = true
2584 }
2585 }
2586 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2587 vid := uint32(metadata)
2588 if vid != ReservedVlan {
2589 ivid = true
2590 }
2591 }
2592 if ovid && ivid {
2593 packetType = DoubleTag
2594 } else if !ovid && !ivid {
2595 packetType = Untagged
2596 } else {
2597 packetType = SingleTag
2598 }
2599 return packetType
2600}
2601
2602//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002603func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002604 logger.Debugw("Adding igmp-trap-of-nni-flow", log.Fields{"classifierInfo": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002605 action := make(map[string]interface{})
2606 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2607 action[TrapToHost] = true
2608 /* We manage flowId resource pool on per PON port basis.
2609 Since this situation is tricky, as a hack, we pass the NNI port
2610 index (network_intf_id) as PON port Index for the flowId resource
2611 pool. Also, there is no ONU Id available for trapping packets
2612 on NNI port, use onu_id as -1 (invalid)
2613 ****************** CAVEAT *******************
2614 This logic works if the NNI Port Id falls within the same valid
2615 range of PON Port Ids. If this doesn't work for some OLT Vendor
2616 we need to have a re-look at this.
2617 *********************************************
2618 */
2619 onuID := -1
2620 uniID := -1
2621 gemPortID := -1
2622 allocID := -1
2623 networkInterfaceID, err := getNniIntfID(classifier, action)
2624 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302625 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002626 "classifier": classifier,
2627 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002628 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002629 }
2630 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302631 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002632 logger.Debug("igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002633 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002634 }
npujarec5762e2020-01-01 14:08:48 +05302635 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002636 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302637 return olterrors.NewErrNotFound("igmp-flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002638 "interface-id": networkInterfaceID,
2639 "onu-id": onuID,
2640 "uni-id": uniID,
2641 "gem-port-id": gemPortID,
2642 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002643 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002644 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002645 classifierProto, err := makeOpenOltClassifierField(classifier)
2646 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002647 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002648 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002649 logger.Debugw("Created classifier proto for the IGMP flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002650 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002651 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002652 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002653 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002654 logger.Debugw("Created action proto for the IGMP flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002655 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2656 OnuId: int32(onuID), // OnuId not required
2657 UniId: int32(uniID), // UniId not used
2658 FlowId: flowID,
2659 FlowType: Downstream,
2660 AllocId: int32(allocID), // AllocId not used
2661 NetworkIntfId: int32(networkInterfaceID),
2662 GemportId: int32(gemPortID), // GemportId not used
2663 Classifier: classifierProto,
2664 Action: actionProto,
2665 Priority: int32(logicalFlow.Priority),
2666 Cookie: logicalFlow.Cookie,
2667 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002668 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002669 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002670 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002671 logger.Debug("IGMP Trap on NNI flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002672 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
2673 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2674 int32(onuID),
2675 int32(uniID),
2676 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002677 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002678 }
2679 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002680}
2681
salmansiddiqui7ac62132019-08-22 03:58:50 +00002682func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2683 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302684 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002685 }
2686 if Dir == tp_pb.Direction_UPSTREAM {
2687 return "upstream", nil
2688 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2689 return "downstream", nil
2690 }
2691 return "", nil
2692}
2693
npujarec5762e2020-01-01 14:08:48 +05302694func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00002695 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
2696 TpID uint32, uni string) {
2697 var gemPort uint32
2698 intfID := args[IntfID]
2699 onuID := args[OnuID]
2700 uniID := args[UniID]
2701 portNo := args[PortNo]
2702 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00002703 if ipProto, ok := classifierInfo[IPProto]; ok {
2704 if ipProto.(uint32) == IPProtoDhcp {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002705 logger.Info("Adding DHCP flow")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002706 if pcp, ok := classifierInfo[VlanPcp]; ok {
2707 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2708 tp_pb.Direction_UPSTREAM,
2709 pcp.(uint32))
2710 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00002711
npujarec5762e2020-01-01 14:08:48 +05302712 f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002713 } else {
2714 //Adding DHCP upstream flow to all gemports
Gamze Abaka724d0852020-03-18 12:10:24 +00002715 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002716 }
2717
2718 } else if ipProto == IgmpProto {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002719 logger.Infow("Adding Us IGMP flow", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "classifierInfo:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002720 if pcp, ok := classifierInfo[VlanPcp]; ok {
2721 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2722 tp_pb.Direction_UPSTREAM,
2723 pcp.(uint32))
npujarec5762e2020-01-01 14:08:48 +05302724 f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002725 } else {
2726 //Adding IGMP upstream flow to all gem ports
Gamze Abaka724d0852020-03-18 12:10:24 +00002727 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002728 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002729 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002730 logger.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002731 return
2732 }
2733 } else if ethType, ok := classifierInfo[EthType]; ok {
2734 if ethType.(uint32) == EapEthType {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002735 logger.Info("Adding EAPOL flow")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002736 var vlanID uint32
2737 if val, ok := classifierInfo[VlanVid]; ok {
2738 vlanID = (val.(uint32)) & VlanvIDMask
2739 } else {
2740 vlanID = DefaultMgmtVlan
2741 }
2742 if pcp, ok := classifierInfo[VlanPcp]; ok {
2743 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2744 tp_pb.Direction_UPSTREAM,
2745 pcp.(uint32))
2746
Girish Gowdrafae935c2020-02-17 19:21:44 +05302747 f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002748 } else {
Gamze Abaka724d0852020-03-18 12:10:24 +00002749 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002750 }
2751 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002752 } else if _, ok := actionInfo[PushVlan]; ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002753 logger.Info("Adding upstream data rule")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002754 if pcp, ok := classifierInfo[VlanPcp]; ok {
2755 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2756 tp_pb.Direction_UPSTREAM,
2757 pcp.(uint32))
2758 //Adding HSIA upstream flow
npujarec5762e2020-01-01 14:08:48 +05302759 f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002760 } else {
2761 //Adding HSIA upstream flow to all gemports
Gamze Abaka724d0852020-03-18 12:10:24 +00002762 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002763 }
2764 } else if _, ok := actionInfo[PopVlan]; ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002765 logger.Info("Adding Downstream data rule")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002766 if pcp, ok := classifierInfo[VlanPcp]; ok {
2767 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05002768 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00002769 pcp.(uint32))
2770 //Adding HSIA downstream flow
npujarec5762e2020-01-01 14:08:48 +05302771 f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002772 } else {
2773 //Adding HSIA downstream flow to all gemports
Gamze Abaka724d0852020-03-18 12:10:24 +00002774 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002775 }
2776 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002777 logger.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002778 return
2779 }
2780 // Send Techprofile download event to child device in go routine as it takes time
2781 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
2782}
2783
Gamze Abakafee36392019-10-03 11:17:24 +00002784func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
2785 flowIDList := f.flowsUsedByGemPort[gemPK]
2786 if len(flowIDList) > 1 {
2787 return true
2788 }
2789 return false
2790}
2791
npujarec5762e2020-01-01 14:08:48 +05302792func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
2793 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002794 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2795 for _, currentGemPort := range currentGemPorts {
2796 for _, tpGemPort := range tpGemPorts {
2797 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2798 return true, currentGemPort
2799 }
2800 }
2801 }
Girish Gowdra54934262019-11-13 14:19:55 +05302802 if tpInst.InstanceCtrl.Onu == "single-instance" {
2803 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
npujarec5762e2020-01-01 14:08:48 +05302804 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID)
2805 f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID)
Girish Gowdra54934262019-11-13 14:19:55 +05302806
2807 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
2808 // still be used on other uni ports.
2809 // So, we need to check and make sure that no other gem port is referring to the given TP ID
2810 // on any other uni port.
npujarec5762e2020-01-01 14:08:48 +05302811 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002812 logger.Debugw("got single instance tp instances", log.Fields{"tpInstances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302813 for i := 0; i < len(tpInstances); i++ {
2814 tpI := tpInstances[i]
2815 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05302816 for _, tpGemPort := range tpGemPorts {
2817 if tpGemPort.GemportID != gemPortID {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002818 logger.Debugw("single instance tp is in use by gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302819 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05302820 }
2821 }
2822 }
2823 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002824 logger.Debug("tech profile is not in use by any gem")
Gamze Abakafee36392019-10-03 11:17:24 +00002825 return false, 0
2826}
2827
salmansiddiqui7ac62132019-08-22 03:58:50 +00002828func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002829 for _, field := range flows.GetOfbFields(flow) {
2830 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002831 classifierInfo[EthType] = field.GetEthType()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002832 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002833 } else if field.Type == flows.ETH_DST {
2834 classifierInfo[EthDst] = field.GetEthDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002835 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002836 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002837 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002838 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002839 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002840 classifierInfo[InPort] = field.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002841 logger.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002842 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302843 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00002844 logger.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002845 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002846 classifierInfo[VlanPcp] = field.GetVlanPcp()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002847 logger.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002848 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002849 classifierInfo[UDPDst] = field.GetUdpDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002850 logger.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002851 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002852 classifierInfo[UDPSrc] = field.GetUdpSrc()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002853 logger.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002854 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002855 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002856 logger.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002857 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002858 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002859 logger.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002860 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002861 classifierInfo[Metadata] = field.GetTableMetadata()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002862 logger.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002863 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002864 classifierInfo[TunnelID] = field.GetTunnelId()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002865 logger.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002866 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002867 logger.Errorw("Un supported field type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002868 return
2869 }
2870 }
2871}
2872
2873func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002874 for _, action := range flows.GetActions(flow) {
2875 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002876 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002877 actionInfo[Output] = out.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002878 logger.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002879 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002880 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002881 }
Scott Baker355d1742019-10-24 10:57:52 -07002882 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002883 actionInfo[PopVlan] = true
Girish Kumar2ad402b2020-03-20 19:45:12 +00002884 logger.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002885 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002886 if out := action.GetPush(); out != nil {
2887 if tpid := out.GetEthertype(); tpid != 0x8100 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002888 logger.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002889 } else {
2890 actionInfo[PushVlan] = true
2891 actionInfo[TPID] = tpid
Girish Kumar2ad402b2020-03-20 19:45:12 +00002892 logger.Debugw("action-type-push-vlan",
salmansiddiqui7ac62132019-08-22 03:58:50 +00002893 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
2894 }
2895 }
Scott Baker355d1742019-10-24 10:57:52 -07002896 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002897 if out := action.GetSetField(); out != nil {
2898 if field := out.GetField(); field != nil {
2899 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00002900 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002901 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002902 /*logger.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
Esin Karamanccb714b2019-11-29 15:02:06 +00002903 formulateSetFieldActionInfoFromFlow(field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002904 }
2905 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002906 } else if action.Type == flows.GROUP {
2907 formulateGroupActionInfoFromFlow(action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002908 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002909 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002910 }
2911 }
2912 return nil
2913}
2914
Esin Karamanccb714b2019-11-29 15:02:06 +00002915func formulateSetFieldActionInfoFromFlow(field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
2916 if ofbField := field.GetOfbField(); ofbField != nil {
2917 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
2918 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2919 actionInfo[VlanVid] = vlan & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00002920 logger.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002921 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002922 logger.Error("No Invalid vlan id in set vlan-vid action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002923 }
2924 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002925 logger.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00002926 }
2927 }
2928}
2929
2930func formulateGroupActionInfoFromFlow(action *ofp.OfpAction, actionInfo map[string]interface{}) {
2931 if action.GetGroup() == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002932 logger.Warn("No group entry found in the group action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002933 } else {
2934 actionInfo[GroupID] = action.GetGroup().GroupId
Girish Kumar2ad402b2020-03-20 19:45:12 +00002935 logger.Debugw("action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002936 }
2937}
2938
salmansiddiqui7ac62132019-08-22 03:58:50 +00002939func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002940 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002941 logger.Debug("Controller bound trap flows, getting inport from tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002942 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2943 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002944 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002945 classifierInfo[InPort] = uniPort
Girish Kumar2ad402b2020-03-20 19:45:12 +00002946 logger.Debugw("upstream pon-to-controller-flow,inport-in-tunnelid", log.Fields{"newInPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002947 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05302948 return olterrors.NewErrNotFound("child-in-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002949 "reason": "upstream pon-to-controller-flow, NO-inport-in-tunnelid",
Girish Kumarf26e4882020-03-05 06:49:10 +00002950 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002951 }
2952 }
2953 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002954 logger.Debug("Non-Controller flows, getting uniport from tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002955 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07002956 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002957 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002958 actionInfo[Output] = uniPort
Girish Kumar2ad402b2020-03-20 19:45:12 +00002959 logger.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid", log.Fields{"newOutPort": actionInfo[Output].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002960 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05302961 return olterrors.NewErrNotFound("out-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002962 "reason": "downstream-nni-to-pon-port-flow, no-outport-in-tunnelid",
Girish Kumarf26e4882020-03-05 06:49:10 +00002963 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002964 }
2965 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2966 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002967 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002968 classifierInfo[InPort] = uniPort
Girish Kumar2ad402b2020-03-20 19:45:12 +00002969 logger.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
David K. Bainbridge82efc492019-09-04 09:57:11 -07002970 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002971 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05302972 return olterrors.NewErrNotFound("nni-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002973 "reason": "upstream-pon-to-nni-port-flow, no-inport-in-tunnelid",
2974 "in-port": classifierInfo[InPort].(uint32),
2975 "out-port": actionInfo[Output].(uint32),
Girish Kumarf26e4882020-03-05 06:49:10 +00002976 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002977 }
2978 }
2979 }
2980 return nil
2981}
Gamze Abakafee36392019-10-03 11:17:24 +00002982
Chaitrashree G S90a17952019-11-14 21:51:21 -05002983func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00002984 /* Metadata 8 bytes:
2985 Most Significant 2 Bytes = Inner VLAN
2986 Next 2 Bytes = Tech Profile ID(TPID)
2987 Least Significant 4 Bytes = Port ID
2988 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
2989 subscriber related flows.
2990 */
2991 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
2992 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00002993 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00002994 }
2995 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002996 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00002997}
2998
2999func appendUnique(slice []uint32, item uint32) []uint32 {
3000 for _, sliceElement := range slice {
3001 if sliceElement == item {
3002 return slice
3003 }
3004 }
3005 return append(slice, item)
3006}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303007
3008// getNniIntfID gets nni intf id from the flow classifier/action
3009func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
3010
3011 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3012 if portType == voltha.Port_PON_OLT {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003013 intfID, err := IntfIDFromNniPortNum(action[Output].(uint32))
3014 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003015 logger.Debugw("invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003016 log.Fields{
3017 "port-number": action[Output].(uint32),
3018 "error": err})
3019 return uint32(0), err
3020 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00003021 logger.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303022 return intfID, nil
3023 } else if portType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003024 intfID, err := IntfIDFromNniPortNum(classifier[InPort].(uint32))
3025 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003026 logger.Debugw("invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003027 log.Fields{
3028 "port-number": action[Output].(uint32),
3029 "error": err})
3030 return uint32(0), err
3031 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00003032 logger.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303033 return intfID, nil
3034 }
3035 return uint32(0), nil
3036}
3037
3038// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
npujarec5762e2020-01-01 14:08:48 +05303039func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303040 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
3041
3042 f.lockCache.Lock()
3043 defer f.lockCache.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003044 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303045 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003046 if lookupGemPort == gemPort {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003047 logger.Debugw("pktin key/value found in cache , no need to update kv as we are assuming both will be in sync",
Matt Jeanneret1719a072019-12-20 14:50:14 -05003048 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
3049 return
3050 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303051 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003052 f.packetInGemPort[pktInkey] = gemPort
3053
npujarec5762e2020-01-01 14:08:48 +05303054 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Girish Kumar2ad402b2020-03-20 19:45:12 +00003055 logger.Debugw("pktin key not found in local cache or value is different. updating cache and kv store", log.Fields{"pktinkey": pktInkey, "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303056 return
3057}
3058
3059// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303060func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303061
3062 f.lockCache.Lock()
3063 defer f.lockCache.Unlock()
3064 onugem := f.onuGemInfo[intfID]
3065 for idx, onu := range onugem {
3066 if onu.OnuID == onuID {
3067 for _, uni := range onu.UniPorts {
3068 if uni == portNum {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003069 logger.Debugw("uni already in cache, no need to update cache and kv store",
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303070 log.Fields{"uni": portNum})
3071 return
3072 }
3073 }
3074 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3075 f.onuGemInfo[intfID] = onugem
3076 }
3077 }
npujarec5762e2020-01-01 14:08:48 +05303078 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303079}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303080
npujarec5762e2020-01-01 14:08:48 +05303081func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3082 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303083 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003084 logger.Error("Failed to get flowid list per gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303085 return
3086 }
3087 for gem, FlowIDs := range flowIDsList {
3088 gemPK := gemPortKey{intf, uint32(gem)}
3089 f.flowsUsedByGemPort[gemPK] = FlowIDs
3090 }
3091 return
3092}
Esin Karamanccb714b2019-11-29 15:02:06 +00003093
3094//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
3095//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05303096func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
3097 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00003098 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003099 logger.Error("Failed to get pon interface to multicast queue map")
Esin Karamanccb714b2019-11-29 15:02:06 +00003100 return
3101 }
3102 for intf, queueInfo := range storedMulticastQueueMap {
3103 q := queueInfoBrief{
3104 gemPortID: queueInfo[0],
3105 servicePriority: queueInfo[1],
3106 }
3107 f.interfaceToMcastQueueMap[intf] = &q
3108 }
3109}
3110
3111//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
3112//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
3113//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05303114func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
3115 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00003116 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003117 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00003118 }
3119 if exists {
3120 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
3121 }
3122 return nil, exists, nil
3123}
3124
3125func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
3126 groupDesc := ofp.OfpGroupDesc{
3127 Type: ofp.OfpGroupType_OFPGT_ALL,
3128 GroupId: groupID,
3129 }
3130 groupEntry := ofp.OfpGroupEntry{
3131 Desc: &groupDesc,
3132 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003133 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003134 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00003135 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003136 bucket := ofp.OfpBucket{
3137 Actions: acts,
3138 }
3139 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00003140 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003141 return &groupEntry
3142}